public void Compile(GraphicsDevice graphicsDevice, EffectDescriptorSetReflection descriptorSetLayouts, EffectBytecode effectBytecode)
        {
            resourceGroupBindings = new ResourceGroupBinding[descriptorSetLayouts.Layouts.Count];
            for (int setIndex = 0; setIndex < descriptorSetLayouts.Layouts.Count; setIndex++)
            {
                var layout = descriptorSetLayouts.Layouts[setIndex].Layout;
                if (layout == null)
                {
                    resourceGroupBindings[setIndex] = new ResourceGroupBinding { ConstantBufferSlot = -1 };
                    continue;
                }

                var resourceGroupBinding = new ResourceGroupBinding();

                for (int resourceIndex = 0; resourceIndex < layout.Entries.Count; resourceIndex++)
                {
                    var layoutEntry = layout.Entries[resourceIndex];

                    if (layoutEntry.Class == EffectParameterClass.ConstantBuffer)
                    {
                        var constantBuffer = effectBytecode.Reflection.ConstantBuffers.First(x => x.Name == layoutEntry.Key.Name);
                        resourceGroupBinding.ConstantBufferSlot = resourceIndex;
                        resourceGroupBinding.ConstantBufferPreallocated = Buffer.Constant.New(graphicsDevice, constantBuffer.Size);
                    }
                }

                resourceGroupBindings[setIndex] = resourceGroupBinding;
            }
        }
        public static EffectDescriptorSetReflection New(GraphicsDevice graphicsDevice, EffectBytecode effectBytecode, List<string> effectDescriptorSetSlots, string defaultSetSlot)
        {
            // Find resource groups
            // TODO: We should precompute most of that at compile time in BytecodeReflection
            // just waiting for format to be more stable
            var descriptorSetLayouts = new EffectDescriptorSetReflection { DefaultSetSlot = defaultSetSlot };
            foreach (var effectDescriptorSetSlot in effectDescriptorSetSlots)
            {
                // Find all resources related to this slot name
                // NOTE: Ordering is mirrored by GLSL layout in Vulkan
                var descriptorSetLayoutBuilder = new DescriptorSetLayoutBuilder();
                bool hasBindings = false;
                foreach (var resourceBinding in effectBytecode.Reflection.ResourceBindings
                    .Where(x => x.ResourceGroup == effectDescriptorSetSlot || (effectDescriptorSetSlot == defaultSetSlot && (x.ResourceGroup == null || x.ResourceGroup == "Globals")))
                    .GroupBy(x => new { Key = x.KeyInfo.Key, Class = x.Class, Type = x.Type, SlotCount = x.SlotCount, LogicalGroup = x.LogicalGroup })
                    .OrderBy(x => x.Key.Class == EffectParameterClass.ConstantBuffer ? 0 : 1)) // Note: Putting cbuffer first for now
                {
                    SamplerState samplerState = null;
                    if (resourceBinding.Key.Class == EffectParameterClass.Sampler)
                    {
                        var matchingSamplerState = effectBytecode.Reflection.SamplerStates.FirstOrDefault(x => x.Key == resourceBinding.Key.Key);
                        if (matchingSamplerState != null)
                            samplerState = SamplerState.New(graphicsDevice, matchingSamplerState.Description);
                    }
                    hasBindings = true;

                    descriptorSetLayoutBuilder.AddBinding(resourceBinding.Key.Key, resourceBinding.Key.LogicalGroup, resourceBinding.Key.Class, resourceBinding.Key.Type, resourceBinding.Key.SlotCount, samplerState);
                }

                descriptorSetLayouts.AddLayout(effectDescriptorSetSlot, hasBindings ? descriptorSetLayoutBuilder : null);
            }

            return descriptorSetLayouts;
        }
 private EffectProgram(GraphicsDevice device, EffectBytecode bytecode)
     : base(device)
 {
     effectBytecode = bytecode;
     Reflection = effectBytecode.Reflection;
     CreateShaders();
 }
示例#4
0
 public PhysicsDebugEffect(GraphicsDevice graphicsDevice)
     : base(graphicsDevice, bytecode ?? (bytecode = EffectBytecode.FromBytesSafe(binaryBytecode)))
 {
     parameters = new ParameterCollection();
     Color = new Color4(1.0f);
     WorldViewProj = Matrix.Identity;
     UseUv = true;
 }
示例#5
0
 public EffectProgram GetOrCreateShader(GraphicsDevice graphicsDevice, EffectBytecode bytecode)
 {
     lock (ShaderLibrary)
     {
         EffectProgram effectProgram;
         if (!ShaderLibrary.TryGetValue(bytecode, out effectProgram))
         {
             effectProgram = new EffectProgram(graphicsDevice, bytecode);
             ShaderLibrary.Add(bytecode, effectProgram);
         }
         return effectProgram;
     }
 }
示例#6
0
        private EffectProgram(GraphicsDevice device, EffectBytecode bytecode)
            : base(device)
        {
            effectBytecode = bytecode;

            // make a copy of the effect's reflection before modifying it.
            Reflection = new EffectReflection
            {
                // The members that are not modified and can be shallowly copied.
                SamplerStates = effectBytecode.Reflection.SamplerStates,
                ShaderStreamOutputDeclarations = effectBytecode.Reflection.ShaderStreamOutputDeclarations,
                StreamOutputRasterizedStream = effectBytecode.Reflection.StreamOutputRasterizedStream,
                StreamOutputStrides = effectBytecode.Reflection.StreamOutputStrides,

                // The members that are modified and should be deeply copied.
                ConstantBuffers = effectBytecode.Reflection.ConstantBuffers.Select(cb => cb.Clone()).ToList(),
                ResourceBindings = new List<EffectParameterResourceData>(effectBytecode.Reflection.ResourceBindings),
            };

            CreateShaders();
        }
        public void Compile(GraphicsDevice graphicsDevice, EffectDescriptorSetReflection descriptorSetLayouts, EffectBytecode effectBytecode)
        {
            descriptorSetBindings = new BindingOperation[descriptorSetLayouts.Layouts.Count][];
            for (int setIndex = 0; setIndex < descriptorSetLayouts.Layouts.Count; setIndex++)
            {
                var layout = descriptorSetLayouts.Layouts[setIndex].Layout;
                if (layout == null)
                    continue;

                var bindingOperations = new List<BindingOperation>();

                for (int resourceIndex = 0; resourceIndex < layout.Entries.Count; resourceIndex++)
                {
                    var layoutEntry = layout.Entries[resourceIndex];

                    // Find it in shader reflection
                    foreach (var resourceBinding in effectBytecode.Reflection.ResourceBindings)
                    {
                        if (resourceBinding.Stage == ShaderStage.None)
                            continue;

                        if (resourceBinding.KeyInfo.Key == layoutEntry.Key)
                        {
                            bindingOperations.Add(new BindingOperation
                            {
                                EntryIndex = resourceIndex,
                                Class = resourceBinding.Class,
                                Stage = resourceBinding.Stage,
                                SlotStart = resourceBinding.SlotStart,
                                ImmutableSampler = layoutEntry.ImmutableSampler,
                            });
                        }
                    }
                }

                descriptorSetBindings[setIndex] = bindingOperations.Count > 0 ? bindingOperations.ToArray() : null;
            }
        }
示例#8
0
        internal EffectProgram(GraphicsDevice device, EffectBytecode bytecode, bool emulateDepthClamp) : base(device)
        {
            effectBytecode = bytecode;
            this.emulateDepthClamp = emulateDepthClamp;

            // TODO OPENGL currently we modify the reflection info; need to find a better way to deal with that
            Reflection = effectBytecode.Reflection;
            CreateShaders();
        }
        protected override void DrawCore(RenderDrawContext context)
        {
            if (EffectInstance.UpdateEffect(GraphicsDevice) || pipelineStateDirty || previousBytecode != EffectInstance.Effect.Bytecode)
            {
                // The EffectInstance might have been updated from outside
                previousBytecode = EffectInstance.Effect.Bytecode;

                pipelineState.State.RootSignature = EffectInstance.RootSignature;
                pipelineState.State.EffectBytecode = EffectInstance.Effect.Bytecode;
                pipelineState.State.BlendState = blendState;
                pipelineState.State.Output.CaptureState(context.CommandList);
                pipelineState.Update();
                pipelineStateDirty = false;
            }

            context.CommandList.SetPipelineState(pipelineState.CurrentState);

            EffectInstance.Apply(context.GraphicsContext);

            // Draw a full screen quad
            context.GraphicsDevice.PrimitiveQuad.Draw(context.CommandList);
        }
        public static void Write(string name, CompilerParameters parameters, EffectBytecode effectData, TextWriter writer)
        {
            const string codeTemplate = @"//------------------------------------------------------------------------------
// <auto-generated>
//     Xenko Effect Compiler File Generated:
{0}//
//     Command Line: {7}
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace {1} 
{{
    {2} class {3}
    {{
        {4} static readonly byte[] {5} = new byte[] {{
{6}
        }};
    }}
}}
";
            var effectToGenerateText = new StringBuilder();
            effectToGenerateText.AppendFormat("//     Effect [{0}]\r\n", name);

            var buffer = new MemoryStream();
            effectData.WriteTo(buffer);

            var bufferAsText = new StringBuilder();
            var bufferArray = buffer.ToArray();
            for (int i = 0; i < bufferArray.Length; i++)
            {
                bufferAsText.Append(bufferArray[i]).Append(", ");
                if (i > 0 && (i % 64) == 0)
                {
                    bufferAsText.AppendLine();
                }
            }

            var classDeclaration = parameters.Get(EffectSourceCodeKeys.ClassDeclaration);
            var fieldDeclaration = parameters.Get(EffectSourceCodeKeys.FieldDeclaration);
            var nameSpace = parameters.Get(EffectSourceCodeKeys.Namespace);
            var className = parameters.Get(EffectSourceCodeKeys.ClassName) ?? name;
            var fieldName = parameters.Get(EffectSourceCodeKeys.FieldName);

            var commandLine = string.Join(" ", Environment.GetCommandLineArgs());

            var graphicsPlatform = parameters.EffectParameters.Platform;
            string xenkoDefine = "undefined";
            switch (graphicsPlatform)
            {
                case GraphicsPlatform.Direct3D11:
                case GraphicsPlatform.Direct3D12:
                    xenkoDefine = "SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D";
                    break;
                case GraphicsPlatform.OpenGL:
                    xenkoDefine = "SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLCORE";
                    break;
                case GraphicsPlatform.OpenGLES:
                    xenkoDefine = "SILICONSTUDIO_XENKO_GRAPHICS_API_OPENGLES";
                    break;
                case GraphicsPlatform.Vulkan:
                    xenkoDefine = "SILICONSTUDIO_XENKO_GRAPHICS_API_VULKAN";
                    break;
            }

            writer.WriteLine("#if {0}", xenkoDefine);
            writer.Write(codeTemplate,
                         effectToGenerateText, // {0} 
                         nameSpace,            // {1} 
                         classDeclaration,     // {2} 
                         className,            // {3} 
                         fieldDeclaration,     // {4} 
                         fieldName,            // {5} 
                         bufferAsText,         // {6}
                         commandLine);         // {7}

            writer.WriteLine("#endif");

            writer.Flush();
        }
        protected override void DrawCore(RenderDrawContext context)
        {
            if (string.IsNullOrEmpty(ShaderSourceName))
                return;

            Parameters.Set(ComputeEffectShaderKeys.ThreadNumbers, ThreadNumbers);
            Parameters.Set(ComputeEffectShaderKeys.ComputeShaderName, ShaderSourceName);
            Parameters.Set(ComputeShaderBaseKeys.ThreadGroupCountGlobal, ThreadGroupCounts);

            if (EffectInstance.UpdateEffect(GraphicsDevice) || pipelineStateDirty || previousBytecode != EffectInstance.Effect.Bytecode)
            {
                // The EffectInstance might have been updated from outside
                previousBytecode = EffectInstance.Effect.Bytecode;

                pipelineState.State.SetDefaults();
                pipelineState.State.RootSignature = EffectInstance.RootSignature;
                pipelineState.State.EffectBytecode = EffectInstance.Effect.Bytecode;
                pipelineState.Update();
                pipelineStateDirty = false;
            }

            // Apply pipeline state
            context.CommandList.SetPipelineState(pipelineState.CurrentState);

            // Apply the effect
            EffectInstance.Apply(context.GraphicsContext);

            // Draw a full screen quad
            context.CommandList.Dispatch(ThreadGroupCounts.X, ThreadGroupCounts.Y, ThreadGroupCounts.Z);

            // Un-apply
            //throw new InvalidOperationException();
            //EffectInstance.Effect.UnbindResources(GraphicsDevice);
        }
示例#12
0
 public static EffectProgram New(GraphicsDevice graphicsDevice, EffectBytecode bytecode)
 {
     var effectProgramLibrary = graphicsDevice.GetOrCreateSharedData(GraphicsDeviceSharedDataType.PerDevice, typeof(EffectProgram), d => new EffectProgramLibrary());
     return effectProgramLibrary.GetOrCreateShader(graphicsDevice, bytecode);
 }