public Program(IShader[] shaders, TransformFeedbackDescriptor[] transformFeedbackDescriptors) { _ubBindingPoints = new int[UbsPerStage * ShaderStages]; _sbBindingPoints = new int[SbsPerStage * ShaderStages]; _textureUnits = new int[TexsPerStage * ShaderStages]; _imageUnits = new int[ImgsPerStage * ShaderStages]; for (int index = 0; index < _ubBindingPoints.Length; index++) { _ubBindingPoints[index] = -1; } for (int index = 0; index < _sbBindingPoints.Length; index++) { _sbBindingPoints[index] = -1; } for (int index = 0; index < _textureUnits.Length; index++) { _textureUnits[index] = -1; } for (int index = 0; index < _imageUnits.Length; index++) { _imageUnits[index] = -1; } Handle = GL.CreateProgram(); for (int index = 0; index < shaders.Length; index++) { int shaderHandle = ((Shader)shaders[index]).Handle; GL.AttachShader(Handle, shaderHandle); } if (transformFeedbackDescriptors != null) { List <string> varyings = new List <string>(); int cbi = 0; foreach (var tfd in transformFeedbackDescriptors.OrderBy(x => x.BufferIndex)) { if (tfd.VaryingLocations.Length == 0) { continue; } while (cbi < tfd.BufferIndex) { varyings.Add("gl_NextBuffer"); cbi++; } int stride = Math.Min(128 * 4, (tfd.Stride + 3) & ~3); int j = 0; for (; j < tfd.VaryingLocations.Length && j * 4 < stride; j++) { byte location = tfd.VaryingLocations[j]; varyings.Add(Varying.GetName(location) ?? "gl_SkipComponents1"); j += Varying.GetSize(location) - 1; } int feedbackBytes = j * 4; while (feedbackBytes < stride) { int bytes = Math.Min(16, stride - feedbackBytes); varyings.Add($"gl_SkipComponents{(bytes / 4)}"); feedbackBytes += bytes; } } GL.TransformFeedbackVaryings(Handle, varyings.Count, varyings.ToArray(), TransformFeedbackMode.InterleavedAttribs); } GL.LinkProgram(Handle); for (int index = 0; index < shaders.Length; index++) { int shaderHandle = ((Shader)shaders[index]).Handle; GL.DetachShader(Handle, shaderHandle); } CheckProgramLink(); Bind(); int ubBindingPoint = 0; int sbBindingPoint = 0; int textureUnit = 0; int imageUnit = 0; for (int index = 0; index < shaders.Length; index++) { Shader shader = (Shader)shaders[index]; foreach (BufferDescriptor descriptor in shader.Info.CBuffers) { int location = GL.GetUniformBlockIndex(Handle, descriptor.Name); if (location < 0) { continue; } GL.UniformBlockBinding(Handle, location, ubBindingPoint); int bpIndex = (int)shader.Stage << UbStageShift | descriptor.Slot; _ubBindingPoints[bpIndex] = ubBindingPoint; ubBindingPoint++; } foreach (BufferDescriptor descriptor in shader.Info.SBuffers) { int location = GL.GetProgramResourceIndex(Handle, ProgramInterface.ShaderStorageBlock, descriptor.Name); if (location < 0) { continue; } GL.ShaderStorageBlockBinding(Handle, location, sbBindingPoint); int bpIndex = (int)shader.Stage << SbStageShift | descriptor.Slot; _sbBindingPoints[bpIndex] = sbBindingPoint; sbBindingPoint++; } int samplerIndex = 0; foreach (TextureDescriptor descriptor in shader.Info.Textures) { int location = GL.GetUniformLocation(Handle, descriptor.Name); if (location < 0) { continue; } GL.Uniform1(location, textureUnit); int uIndex = (int)shader.Stage << TexStageShift | samplerIndex++; _textureUnits[uIndex] = textureUnit; textureUnit++; } int imageIndex = 0; foreach (TextureDescriptor descriptor in shader.Info.Images) { int location = GL.GetUniformLocation(Handle, descriptor.Name); if (location < 0) { continue; } GL.Uniform1(location, imageUnit); int uIndex = (int)shader.Stage << ImgStageShift | imageIndex++; _imageUnits[uIndex] = imageUnit; imageUnit++; } } FragmentIsBgraUniform = GL.GetUniformLocation(Handle, "is_bgra"); FragmentRenderScaleUniform = GL.GetUniformLocation(Handle, "fp_renderScale"); ComputeRenderScaleUniform = GL.GetUniformLocation(Handle, "cp_renderScale"); }
public Program(IShader[] shaders, TransformFeedbackDescriptor[] transformFeedbackDescriptors) { Handle = GL.CreateProgram(); for (int index = 0; index < shaders.Length; index++) { int shaderHandle = ((Shader)shaders[index]).Handle; GL.AttachShader(Handle, shaderHandle); } if (transformFeedbackDescriptors != null) { List <string> varyings = new List <string>(); int cbi = 0; foreach (var tfd in transformFeedbackDescriptors.OrderBy(x => x.BufferIndex)) { if (tfd.VaryingLocations.Length == 0) { continue; } while (cbi < tfd.BufferIndex) { varyings.Add("gl_NextBuffer"); cbi++; } int stride = Math.Min(128 * 4, (tfd.Stride + 3) & ~3); int j = 0; for (; j < tfd.VaryingLocations.Length && j * 4 < stride; j++) { byte location = tfd.VaryingLocations[j]; varyings.Add(Varying.GetName(location) ?? "gl_SkipComponents1"); j += Varying.GetSize(location) - 1; } int feedbackBytes = j * 4; while (feedbackBytes < stride) { int bytes = Math.Min(16, stride - feedbackBytes); varyings.Add($"gl_SkipComponents{(bytes / 4)}"); feedbackBytes += bytes; } } GL.TransformFeedbackVaryings(Handle, varyings.Count, varyings.ToArray(), TransformFeedbackMode.InterleavedAttribs); } GL.LinkProgram(Handle); for (int index = 0; index < shaders.Length; index++) { int shaderHandle = ((Shader)shaders[index]).Handle; GL.DetachShader(Handle, shaderHandle); } CheckProgramLink(); FragmentIsBgraUniform = GL.GetUniformLocation(Handle, "is_bgra"); FragmentRenderScaleUniform = GL.GetUniformLocation(Handle, "fp_renderScale"); ComputeRenderScaleUniform = GL.GetUniformLocation(Handle, "cp_renderScale"); }