Example #1
0
        /// <summary>
        /// Dispatches compute work.
        /// </summary>
        /// <param name="state">Current GPU state</param>
        /// <param name="argument">Method call argument</param>
        public void Dispatch(GpuState state, int argument)
        {
            uint qmdAddress = (uint)state.Get <int>(MethodOffset.DispatchParamsAddress);

            var qmd = _context.MemoryAccessor.Read <ComputeQmd>((ulong)qmdAddress << 8);

            GpuVa shaderBaseAddress = state.Get <GpuVa>(MethodOffset.ShaderBaseAddress);

            ulong shaderGpuVa = shaderBaseAddress.Pack() + (uint)qmd.ProgramOffset;

            int localMemorySize = qmd.ShaderLocalMemoryLowSize + qmd.ShaderLocalMemoryHighSize;

            int sharedMemorySize = Math.Min(qmd.SharedMemorySize, _context.Capabilities.MaximumComputeSharedMemorySize);

            ComputeShader cs = ShaderCache.GetComputeShader(
                shaderGpuVa,
                qmd.CtaThreadDimension0,
                qmd.CtaThreadDimension1,
                qmd.CtaThreadDimension2,
                localMemorySize,
                sharedMemorySize);

            _context.Renderer.Pipeline.SetProgram(cs.HostProgram);

            var samplerPool = state.Get <PoolState>(MethodOffset.SamplerPoolState);

            TextureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId, qmd.SamplerIndex);

            var texturePool = state.Get <PoolState>(MethodOffset.TexturePoolState);

            TextureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);

            TextureManager.SetComputeTextureBufferIndex(state.Get <int>(MethodOffset.TextureBufferIndex));

            ShaderProgramInfo info = cs.Shader.Program.Info;

            uint sbEnableMask = 0;
            uint ubEnableMask = 0;

            for (int index = 0; index < Constants.TotalCpUniformBuffers; index++)
            {
                if (!qmd.ConstantBufferValid(index))
                {
                    continue;
                }

                ubEnableMask |= 1u << index;

                ulong gpuVa = (uint)qmd.ConstantBufferAddrLower(index) | (ulong)qmd.ConstantBufferAddrUpper(index) << 32;
                ulong size  = (ulong)qmd.ConstantBufferSize(index);

                BufferManager.SetComputeUniformBuffer(index, gpuVa, size);
            }

            for (int index = 0; index < info.SBuffers.Count; index++)
            {
                BufferDescriptor sb = info.SBuffers[index];

                sbEnableMask |= 1u << sb.Slot;

                ulong sbDescAddress = BufferManager.GetComputeUniformBufferAddress(0);

                int sbDescOffset = 0x310 + sb.Slot * 0x10;

                sbDescAddress += (ulong)sbDescOffset;

                ReadOnlySpan <byte> sbDescriptorData = _context.PhysicalMemory.GetSpan(sbDescAddress, 0x10);

                SbDescriptor sbDescriptor = MemoryMarshal.Cast <byte, SbDescriptor>(sbDescriptorData)[0];

                BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size);
            }

            ubEnableMask = 0;

            for (int index = 0; index < info.CBuffers.Count; index++)
            {
                ubEnableMask |= 1u << info.CBuffers[index].Slot;
            }

            BufferManager.SetComputeStorageBufferEnableMask(sbEnableMask);
            BufferManager.SetComputeUniformBufferEnableMask(ubEnableMask);

            var textureBindings = new TextureBindingInfo[info.Textures.Count];

            for (int index = 0; index < info.Textures.Count; index++)
            {
                var descriptor = info.Textures[index];

                Target target = GetTarget(descriptor.Type);

                if (descriptor.IsBindless)
                {
                    textureBindings[index] = new TextureBindingInfo(target, descriptor.CbufOffset, descriptor.CbufSlot);
                }
                else
                {
                    textureBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
                }
            }

            TextureManager.SetComputeTextures(textureBindings);

            var imageBindings = new TextureBindingInfo[info.Images.Count];

            for (int index = 0; index < info.Images.Count; index++)
            {
                var descriptor = info.Images[index];

                Target target = GetTarget(descriptor.Type);

                imageBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
            }

            TextureManager.SetComputeImages(imageBindings);

            BufferManager.CommitComputeBindings();
            TextureManager.CommitComputeBindings();

            _context.Renderer.Pipeline.DispatchCompute(
                qmd.CtaRasterWidth,
                qmd.CtaRasterHeight,
                qmd.CtaRasterDepth);

            UpdateShaderState(state);
        }
Example #2
0
        public void Run()
        {
            try
            {
                // Load renderer
                renderer = RenderSystem.Load("OpenGL", debugger);

                // Create render context
                var contextDesc = new RenderContextDescriptor();
                {
                    contextDesc.VideoMode.Resolution.Width  = 800;
                    contextDesc.VideoMode.Resolution.Height = 600;
                    contextDesc.VideoMode.ColorBits         = 32;
                    contextDesc.VideoMode.DepthBits         = 24;
                    contextDesc.VideoMode.StencilBits       = 8;
                }
                context = renderer.CreateRenderContext(contextDesc);

                // Get context window
                var window = context.Surface;
                window.Shown = true;

                window.Title = $"LLGL for C# - Texturing ( {renderer.Name} )";

                // Print renderer information
                Console.WriteLine("Renderer Info:");
                var info = renderer.Info;
                {
                    Console.WriteLine($"  Renderer:         {info.RendererName}");
                    Console.WriteLine($"  Device:           {info.DeviceName}");
                    Console.WriteLine($"  Vendor:           {info.VendorName}");
                    Console.WriteLine($"  Shading Language: {info.ShadingLanguageName}");
                }

                // Create vertex buffer
                var vertexFormat = new VertexFormat();
                vertexFormat.AppendAttribute(new VertexAttribute("coord", Format.RG32Float));
                vertexFormat.AppendAttribute(new VertexAttribute("texCoord", Format.RG32Float));

                const float uvScale = 10.0f;

                var vertices = new Vertex[]
                {
                    new Vertex(-0.5f, -0.5f, 0.0f, uvScale),
                    new Vertex(-0.5f, +0.5f, 0.0f, 0.0f),
                    new Vertex(+0.5f, -0.5f, uvScale, uvScale),
                    new Vertex(+0.5f, +0.5f, uvScale, 0.0f),
                };

                var vertexBufferDesc = new BufferDescriptor();
                {
                    vertexBufferDesc.BindFlags           = BindFlags.VertexBuffer;
                    vertexBufferDesc.Size                = vertexFormat.Stride * (ulong)vertices.Length;
                    vertexBufferDesc.VertexBuffer.Format = vertexFormat;
                }
                var vertexBuffer = renderer.CreateBuffer(vertexBufferDesc, vertices);

                // Create shaders
                var vertShader = renderer.CreateShader(
                    new ShaderDescriptor(
                        type: ShaderType.Vertex,
                        sourceType: ShaderSourceType.CodeString,
                        source: @"
                            #version 330 core
                            in vec2 coord;
                            in vec2 texCoord;
                            out vec2 vTexCoord;
                            void main() {
                                gl_Position = vec4(coord, 0, 1);
                                vTexCoord = texCoord;
                            }
                        "
                        )
                    );
                var fragShader = renderer.CreateShader(
                    new ShaderDescriptor
                    (
                        type: ShaderType.Fragment,
                        sourceType: ShaderSourceType.CodeString,
                        source: @"
                            #version 330 core
                            in vec2 vTexCoord;
                            out vec4 fColor;
                            uniform sampler2D tex;
                            void main() {
                                fColor = texture(tex, vTexCoord);
                            }
                        "
                    )
                    );

                var shaderProgramDesc = new ShaderProgramDescriptor();
                {
                    shaderProgramDesc.VertexFormats.Add(vertexFormat);
                    shaderProgramDesc.VertexShader   = vertShader;
                    shaderProgramDesc.FragmentShader = fragShader;
                }
                var shaderProgram = renderer.CreateShaderProgram(shaderProgramDesc);

                if (shaderProgram.HasErrors)
                {
                    throw new Exception(shaderProgram.Report);
                }

                // Create pipeline layout
                var pipelineLayoutDesc = new PipelineLayoutDescriptor();
                {
                    pipelineLayoutDesc.Bindings.Add(
                        new BindingDescriptor(ResourceType.Texture, BindFlags.Sampled, StageFlags.FragmentStage, 0)
                        );
                    pipelineLayoutDesc.Bindings.Add(
                        new BindingDescriptor(ResourceType.Sampler, 0, StageFlags.FragmentStage, 0)
                        );
                }
                var pipelineLayout = renderer.CreatePipelineLayout(pipelineLayoutDesc);

                // Create graphics pipeline
                var pipelineDesc = new GraphicsPipelineDescriptor();
                {
                    pipelineDesc.ShaderProgram                 = shaderProgram;
                    pipelineDesc.PipelineLayout                = pipelineLayout;
                    pipelineDesc.PrimitiveTopology             = PrimitiveTopology.TriangleStrip;
                    pipelineDesc.Blend.Targets[0].BlendEnabled = true;
                }
                pipeline = renderer.CreateGraphicsPipeline(pipelineDesc);

                // Create texture
                var imageDesc = new SrcImageDescriptor <RGBA>();
                {
                    imageDesc.Format   = ImageFormat.RGBA;
                    imageDesc.DataType = DataType.UInt8;
                    imageDesc.Data     = new RGBA[4];
                    imageDesc.Data[0]  = new RGBA(255, 0, 0, 255);
                    imageDesc.Data[1]  = new RGBA(0, 255, 0, 255);
                    imageDesc.Data[2]  = new RGBA(0, 0, 0, 0);
                    imageDesc.Data[3]  = new RGBA(0, 0, 0, 0);
                }
                var textureDesc = new TextureDescriptor();
                {
                    textureDesc.Type   = TextureType.Texture2D;
                    textureDesc.Extent = new Extent3D(2, 2, 1);
                }
                var texture = renderer.CreateTexture(textureDesc, imageDesc);

                // Create sampler
                var samplerDesc = new SamplerDescriptor();
                {
                    samplerDesc.MagFilter = SamplerFilter.Nearest;
                }
                var sampler = renderer.CreateSampler(samplerDesc);

                // Create resource heap
                var resourceHeapDesc = new ResourceHeapDescriptor();
                {
                    resourceHeapDesc.PipelineLayout = pipelineLayout;
                    resourceHeapDesc.ResourceViews.Add(new ResourceViewDescriptor(texture));
                    resourceHeapDesc.ResourceViews.Add(new ResourceViewDescriptor(sampler));
                }
                var resourceHeap = renderer.CreateResourceHeap(resourceHeapDesc);

                // Get command queue
                cmdQueue  = renderer.CommandQueue;
                cmdBuffer = renderer.CreateCommandBuffer();

                cmdBuffer.SetClearColor(0.1f, 0.1f, 0.2f, 1.0f);

                // Render loop
                while (window.ProcessEvents())
                {
                    cmdBuffer.Begin();
                    {
                        cmdBuffer.SetVertexBuffer(vertexBuffer);

                        cmdBuffer.BeginRenderPass(context);
                        {
                            cmdBuffer.Clear(ClearFlags.Color);
                            cmdBuffer.SetViewport(new Viewport(0, 0, context.Resolution.Width, context.Resolution.Height));

                            cmdBuffer.SetGraphicsPipeline(pipeline);
                            cmdBuffer.SetGraphicsResourceHeap(resourceHeap);

                            cmdBuffer.Draw(4, 0);
                        }
                        cmdBuffer.EndRenderPass();
                    }
                    cmdBuffer.End();
                    cmdQueue.Submit(cmdBuffer);

                    context.Present();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                Console.WriteLine("press any key to continue ...");
                Console.ReadKey();
            }
            finally
            {
                RenderSystem.Unload(renderer);
            }
        }
        /// <summary>
        /// Generates expression converting and storing one pixel in output format to output buffer (ordering bytes accordingly to endianess) at given position using channels values provided by red/green/blue/alpha variables.
        /// </summary>
        /// <returns>Generated expression.</returns>
        /// <param name="outputBufferDescriptor">Object containing information about output buffer: color format and endianness.</param>
        /// <param name="outBuffer">Output buffer.</param>
        /// <param name="outPosition">Position of pixel in output buffer.</param>
        /// <param name="color">Object with variables from which value of color channels should be read.</param>
        private static Expression GenerateTo(BufferDescriptor outputBufferDescriptor, ParameterExpression outBuffer, ParameterExpression outPosition, PixelDescriptor color)
        {
            byte currentBit  = 0;
            byte currentByte = 0;
            var  expressions = new List <Expression>();

            Expression currentExpression = null;

            foreach (var colorDescriptor in outputBufferDescriptor.ColorFormat.GetColorsLengths())
            {
                Expression colorExpression = null;

                switch (colorDescriptor.Key)
                {
                case ColorType.A:
                    colorExpression = color.AlphaChannel;
                    break;

                case ColorType.B:
                    colorExpression = color.BlueChannel;
                    break;

                case ColorType.G:
                    colorExpression = color.GreenChannel;
                    break;

                case ColorType.R:
                    colorExpression = color.RedChannel;
                    break;

                case ColorType.X:
                    colorExpression = Expression.Constant((uint)0xFF);
                    break;

                case ColorType.L:
                    throw new ArgumentException("Luminance channel is not allowed in target color format");
                }

                foreach (var transformation in ByteSqueezeAndMove(colorDescriptor.Value, currentBit))
                {
                    Expression currentExpressionFragment = colorExpression;

                    if (transformation.MaskBits != 0xFF)
                    {
                        currentExpressionFragment = Expression.And(currentExpressionFragment, Expression.Constant((uint)transformation.MaskBits));
                    }

                    if (transformation.ShiftBits > 0)
                    {
                        currentExpressionFragment = Expression.RightShift(currentExpressionFragment, Expression.Constant((int)transformation.ShiftBits));
                    }
                    else if (transformation.ShiftBits < 0)
                    {
                        currentExpressionFragment = Expression.And(
                            Expression.LeftShift(currentExpressionFragment, Expression.Constant((int)(-transformation.ShiftBits))),
                            Expression.Constant((uint)0xFF));
                    }

                    currentExpression = (currentExpression == null) ? currentExpressionFragment : Expression.Or(currentExpression, currentExpressionFragment);

                    currentBit += transformation.UsedBits;
                    while (currentBit >= 8)
                    {
                        expressions.Add(
                            Expression.Assign(
                                Expression.ArrayAccess(outBuffer,
                                                       Expression.Add(
                                                           outPosition,
                                                           Expression.Constant((outputBufferDescriptor.DataEndianness == Endianess.BigEndian) ? (int)currentByte : (outputBufferDescriptor.ColorFormat.GetColorDepth() - currentByte - 1)))),
                                Expression.Convert(currentExpression, typeof(byte))));

                        currentExpression = null;
                        currentBit       -= 8;
                        currentByte++;
                    }
                }
            }

            return(Expression.Block(expressions));
        }
        private static BlendDelegate GenerateBlendMethod(BufferDescriptor backgroudBufferDescriptor, BufferDescriptor foregroundBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var outputPixel            = new PixelDescriptor();
            var inputBackgroundPixel   = new PixelDescriptor();
            var inputForegroundPixel   = new PixelDescriptor();
            var contantBackgroundPixel = new PixelDescriptor();

            var vBackPos   = Expression.Variable(typeof(int), "backPos");
            var vFrontPos  = Expression.Variable(typeof(int), "frontPos");
            var vOutPos    = Expression.Variable(typeof(int), "outPos");
            var vBackStep  = Expression.Variable(typeof(int), "backStep");
            var vFrontStep = Expression.Variable(typeof(int), "frontStep");
            var vOutStep   = Expression.Variable(typeof(int), "outStep");
            var vLength    = Expression.Variable(typeof(int), "length");

            var vBackBuffer                 = Expression.Parameter(typeof(byte[]), "backBuffer");
            var vBackClutBuffer             = Expression.Parameter(typeof(byte[]), "backClutBuffer");
            var vFrontBuffer                = Expression.Parameter(typeof(byte[]), "fronBuffer");
            var vFrontClutBuffer            = Expression.Parameter(typeof(byte[]), "frontClutBuffer");
            var vOutputBuffer               = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");
            var vBackgroundColor            = Expression.Parameter(typeof(Pixel), "backgroundColor");
            var vBackBufferAlphaMultiplier  = Expression.Parameter(typeof(byte), "backBufferAlphaMultiplier");
            var vFrontBufferAlphaMultiplier = Expression.Parameter(typeof(byte), "frontBufferAlphaMultiplier");

            var vBackAlphaBlended            = Expression.Variable(typeof(uint), "backAlphaBlended");
            var vBackgroundColorAlphaBlended = Expression.Variable(typeof(uint), "backgroundColorAlphaBlended");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new[] { outputPixel.RedChannel, outputPixel.GreenChannel, outputPixel.BlueChannel, outputPixel.AlphaChannel,
                        inputForegroundPixel.RedChannel, inputForegroundPixel.GreenChannel, inputForegroundPixel.BlueChannel, inputForegroundPixel.AlphaChannel,
                        inputBackgroundPixel.RedChannel, inputBackgroundPixel.GreenChannel, inputBackgroundPixel.BlueChannel, inputBackgroundPixel.AlphaChannel,
                        vBackStep, vFrontStep, vOutStep, vLength, vBackPos, vFrontPos, vOutPos,
                        contantBackgroundPixel.RedChannel, contantBackgroundPixel.GreenChannel, contantBackgroundPixel.BlueChannel, contantBackgroundPixel.AlphaChannel,
                        vBackAlphaBlended, vBackgroundColorAlphaBlended,
                        tmp },

                Expression.Assign(vBackStep, Expression.Constant(backgroudBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vFrontStep, Expression.Constant(foregroundBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vBackBuffer, "Length")),

                Expression.Assign(vBackPos, Expression.Constant(0x00)),
                Expression.Assign(vFrontPos, Expression.Constant(0x00)),
                Expression.Assign(vOutPos, Expression.Constant(0x00)),

                Expression.Assign(contantBackgroundPixel.AlphaChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Alpha"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.RedChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Red"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.GreenChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Green"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.BlueChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Blue"), typeof(uint))),

                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vBackPos, vLength),
                                          Expression.Block(

                                              GenerateFrom(backgroudBufferDescriptor, vBackBuffer, vBackClutBuffer, vBackPos, inputBackgroundPixel, tmp),
                                              GenerateFrom(foregroundBufferDescriptor, vFrontBuffer, vFrontClutBuffer, vFrontPos, inputForegroundPixel, tmp),

                                              Expression.Assign(inputBackgroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputBackgroundPixel.AlphaChannel, Expression.Convert(vBackBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),
                                              Expression.Assign(inputForegroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputForegroundPixel.AlphaChannel, Expression.Convert(vFrontBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),

                                              Expression.Block(
                                                  // (b_alpha * (0xFF - f_alpha)) / 0xFF
                                                  Expression.Assign(
                                                      vBackAlphaBlended,
                                                      Expression.Divide(
                                                          Expression.Multiply(
                                                              inputBackgroundPixel.AlphaChannel,
                                                              Expression.Subtract(
                                                                  Expression.Constant((uint)0xFF),
                                                                  inputForegroundPixel.AlphaChannel)),
                                                          Expression.Constant((uint)0xFF))),

                                                  // (c_alpha * (0xFF - (f_alpha + b_alpha * (0xFF - f_alpha)))) / 0xFF
                                                  Expression.Assign(
                                                      vBackgroundColorAlphaBlended,
                                                      Expression.Divide(
                                                          Expression.Multiply(
                                                              contantBackgroundPixel.AlphaChannel,
                                                              Expression.Subtract(
                                                                  Expression.Constant((uint)0xFF),
                                                                  Expression.Add(
                                                                      inputForegroundPixel.AlphaChannel,
                                                                      vBackAlphaBlended))),
                                                          Expression.Constant((uint)0xFF))),

                                                  Expression.Assign(
                                                      outputPixel.AlphaChannel,
                                                      Expression.Add(
                                                          inputForegroundPixel.AlphaChannel,
                                                          Expression.Add(
                                                              vBackAlphaBlended,
                                                              vBackgroundColorAlphaBlended))),

                                                  Expression.IfThenElse(
                                                      Expression.Equal(outputPixel.AlphaChannel, Expression.Constant((uint)0)),
                                                      Expression.Block(
                                                          Expression.Assign(outputPixel.RedChannel, contantBackgroundPixel.RedChannel),
                                                          Expression.Assign(outputPixel.GreenChannel, contantBackgroundPixel.GreenChannel),
                                                          Expression.Assign(outputPixel.BlueChannel, contantBackgroundPixel.BlueChannel),
                                                          Expression.Assign(outputPixel.AlphaChannel, contantBackgroundPixel.AlphaChannel)),
                                                      Expression.Block(
                                                          Expression.Assign(
                                                              outputPixel.RedChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.RedChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.RedChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.RedChannel)),
                                                                  outputPixel.AlphaChannel)),
                                                          Expression.Assign(
                                                              outputPixel.GreenChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.GreenChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.GreenChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.GreenChannel)),
                                                                  outputPixel.AlphaChannel)),
                                                          Expression.Assign(
                                                              outputPixel.BlueChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.BlueChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.BlueChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.BlueChannel)),
                                                                  outputPixel.AlphaChannel))))
                                                  ),

                                              GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, outputPixel),

                                              Expression.AddAssign(vBackPos, vBackStep),
                                              Expression.AddAssign(vFrontPos, vFrontStep),
                                              Expression.AddAssign(vOutPos, vOutStep)
                                              ),
                                          Expression.Break(outOfLoop)
                                          ),
                    outOfLoop
                    )
                );

            return(Expression.Lambda <BlendDelegate>(block, vBackBuffer, vBackClutBuffer, vFrontBuffer, vFrontClutBuffer, vOutputBuffer, vBackgroundColor, vBackBufferAlphaMultiplier, vFrontBufferAlphaMultiplier).Compile());
        }
        private static ConvertDelegate GenerateConvertMethod(BufferDescriptor inputBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var vColor = new PixelDescriptor();

            var vInStep  = Expression.Variable(typeof(int), "inStep");
            var vOutStep = Expression.Variable(typeof(int), "outStep");
            var vLength  = Expression.Variable(typeof(int), "length");

            var vInputBuffer  = Expression.Parameter(typeof(byte[]), "inputBuffer");
            var vClutBuffer   = Expression.Parameter(typeof(byte[]), "clutBuffer");
            var vOutputBuffer = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");

            var vInPos  = Expression.Variable(typeof(int), "inPos");
            var vOutPos = Expression.Variable(typeof(int), "outPos");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new [] { vColor.RedChannel, vColor.GreenChannel, vColor.BlueChannel, vColor.AlphaChannel, vInStep, vOutStep, vLength, vInPos, vOutPos, tmp },

                Expression.Assign(vInStep, Expression.Constant(inputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vInputBuffer, "Length")),

                Expression.Assign(vInPos, Expression.Constant(0)),
                Expression.Assign(vOutPos, Expression.Constant(0)),
                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vInPos, vLength),
                                          Expression.Block(
                                              GenerateFrom(inputBufferDescriptor, vInputBuffer, vClutBuffer, vInPos, vColor, tmp),
                                              GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, vColor),

                                              Expression.AddAssign(vInPos, vInStep),
                                              Expression.AddAssign(vOutPos, vOutStep)
                                              ),
                                          Expression.Break(outOfLoop)
                                          ),
                    outOfLoop
                    )
                );

            return(Expression.Lambda <ConvertDelegate>(block, vInputBuffer, vClutBuffer, vOutputBuffer).Compile());
        }
        /// <summary>
        /// Generates expression reading one pixel encoded in given format from input buffer (with bytes ordered accordingly to endianess) at given position
        /// and storing each channel in separate variable expression.
        /// </summary>
        /// <returns>Generated expression.</returns>
        /// <param name="inputBufferDescriptor">Object containing information about input buffer: color format and endianness.</param>
        /// <param name="inBuffer">Input buffer.</param>
        /// <param name="clutBuffer">Color look-up table buffer.</param>
        /// <param name="inPosition">Position of pixel in buffer.</param>
        /// <param name="color">Variable where values of color channels should be stored.</param>
        private static Expression GenerateFrom(BufferDescriptor inputBufferDescriptor, ParameterExpression inBuffer, ParameterExpression clutBuffer, Expression inPosition, PixelDescriptor color, Expression tmp)
        {
            byte currentBit  = 0;
            byte currentByte = 0;
            bool isAlphaSet  = false;

            var expressions = new List <Expression>();
            var inputBytes  = new ParameterExpression[inputBufferDescriptor.ColorFormat.GetColorDepth()];

            for (int i = 0; i < inputBytes.Length; i++)
            {
                inputBytes[i] = Expression.Variable(typeof(uint));

                expressions.Add(
                    Expression.Assign(
                        inputBytes[i],
                        Expression.Convert(
                            Expression.ArrayIndex(
                                inBuffer,
                                Expression.Add(
                                    inPosition,
                                    Expression.Constant((inputBufferDescriptor.DataEndianness == Endianess.BigEndian) ? i : inputBytes.Length - i - 1))),
                            typeof(uint))));
            }

            foreach (var colorDescriptor in inputBufferDescriptor.ColorFormat.GetColorsLengths())
            {
                Expression colorExpression = null;

                foreach (var transformation in ByteInflate(colorDescriptor.Value, currentBit))
                {
                    Expression currentExpressionFragment = inputBytes[currentByte];

                    if (transformation.MaskBits != 0xFF)
                    {
                        currentExpressionFragment = Expression.And(currentExpressionFragment, Expression.Constant((uint)transformation.MaskBits));
                    }

                    if (transformation.ShiftBits > 0)
                    {
                        currentExpressionFragment = Expression.RightShift(currentExpressionFragment, Expression.Constant((int)transformation.ShiftBits));
                    }
                    else if (transformation.ShiftBits < 0)
                    {
                        currentExpressionFragment = Expression.And(
                            Expression.LeftShift(currentExpressionFragment, Expression.Constant((int)(-transformation.ShiftBits))),
                            Expression.Constant((uint)0xFF));
                    }

                    currentBit += transformation.UsedBits;
                    if (currentBit >= 8)
                    {
                        currentBit -= 8;
                        currentByte++;
                    }

                    colorExpression = (colorExpression == null) ? currentExpressionFragment : Expression.Or(colorExpression, currentExpressionFragment);
                }

                if (colorDescriptor.Key == ColorType.X)
                {
                    continue;
                }

                // luminance - indirect color indexing using CLUT
                if (colorDescriptor.Key == ColorType.L)
                {
                    if (!inputBufferDescriptor.ClutColorFormat.HasValue)
                    {
                        throw new ArgumentException("CLUT mode required but not set");
                    }

                    var clutWidth  = Expression.Constant((uint)inputBufferDescriptor.ClutColorFormat.Value.GetColorDepth());
                    var clutOffset = Expression.Multiply(colorExpression, clutWidth);

                    expressions.Add(Expression.Assign(tmp, color.AlphaChannel));

                    // todo: indirect parameters should not be needed here, but we  m u s t  pass something
                    expressions.Add(
                        GenerateFrom(new BufferDescriptor
                    {
                        ColorFormat    = inputBufferDescriptor.ClutColorFormat.Value,
                        DataEndianness = inputBufferDescriptor.DataEndianness
                    }, clutBuffer, clutBuffer, Expression.Convert(clutOffset, typeof(int)), color, tmp));

                    expressions.Add(Expression.Assign(color.AlphaChannel, tmp));
                }
                else
                {
                    Expression currentColor = null;
                    switch (colorDescriptor.Key)
                    {
                    case ColorType.A:
                        currentColor = color.AlphaChannel;
                        isAlphaSet   = true;
                        break;

                    case ColorType.B:
                        currentColor = color.BlueChannel;
                        break;

                    case ColorType.G:
                        currentColor = color.GreenChannel;
                        break;

                    case ColorType.R:
                        currentColor = color.RedChannel;
                        break;
                    }

                    expressions.Add(Expression.Assign(currentColor, colorExpression));

                    // filling lsb '0'-bits with copy of msb pattern
                    var numberOfBits = colorDescriptor.Value;
                    var zeroBits     = 8 - numberOfBits;
                    while (zeroBits > 0)
                    {
                        expressions.Add(Expression.OrAssign(
                                            currentColor,
                                            Expression.RightShift(
                                                currentColor,
                                                Expression.Constant((int)numberOfBits))));
                        zeroBits -= numberOfBits;
                    }
                }
            }

            if (!isAlphaSet)
            {
                expressions.Add(Expression.Assign(color.AlphaChannel, Expression.Constant((uint)0xFF)));
            }
            return(Expression.Block(inputBytes, expressions));
        }
        private static ConvertDelegate GenerateConvertMethod(BufferDescriptor inputBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var vColor = new PixelDescriptor();

            var vInStep  = Expression.Variable(typeof(int), "inStep");
            var vOutStep = Expression.Variable(typeof(int), "outStep");
            var vLength  = Expression.Variable(typeof(int), "length");

            var vInputBuffer      = Expression.Parameter(typeof(byte[]), "inputBuffer");
            var vClutBuffer       = Expression.Parameter(typeof(byte[]), "clutBuffer");
            var vAlpha            = Expression.Parameter(typeof(byte), "alpha");
            var vAlphaReplaceMode = Expression.Parameter(typeof(PixelBlendingMode), "alphaReplaceMode");
            var vOutputBuffer     = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");

            var vInPos  = Expression.Variable(typeof(int), "inPos");
            var vOutPos = Expression.Variable(typeof(int), "outPos");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new [] { vColor.RedChannel, vColor.GreenChannel, vColor.BlueChannel, vColor.AlphaChannel, vInStep, vOutStep, vLength, vInPos, vOutPos, tmp },

                Expression.Assign(vInStep, Expression.Constant(inputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vInputBuffer, "Length")),

                Expression.Assign(vInPos, Expression.Constant(0)),
                Expression.Assign(vOutPos, Expression.Constant(0)),
                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vInPos, vLength),
                                          Expression.Block(
                                              GenerateFrom(inputBufferDescriptor, vInputBuffer, vClutBuffer, vInPos, vColor, tmp),

                                              // handle the case where alpha needs to be changed
                                              Expression.Switch(typeof(void), vAlphaReplaceMode, null, null, new SwitchCase[]
            {
                // Multiply
                Expression.SwitchCase(
                    Expression.Assign(vColor.AlphaChannel, Expression.Divide(Expression.Multiply(vColor.AlphaChannel, Expression.Convert(vAlpha, typeof(uint))), Expression.Constant((uint)0xFF))),
                    Expression.Constant(PixelBlendingMode.Multiply)
                    ),

                // Replace
                Expression.SwitchCase(
                    Expression.Assign(vColor.AlphaChannel, Expression.Convert(vAlpha, typeof(uint))),
                    Expression.Constant(PixelBlendingMode.Replace)
                    )
            }),

                                              GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, vColor),

                                              Expression.AddAssign(vInPos, vInStep),
                                              Expression.AddAssign(vOutPos, vOutStep)
                                              ),
                                          Expression.Break(outOfLoop)
                                          ),
                    outOfLoop
                    )
                );

            return(Expression.Lambda <ConvertDelegate>(block, vInputBuffer, vClutBuffer, vAlpha, vAlphaReplaceMode, vOutputBuffer).Compile());
        }
Example #8
0
        /// <summary>
        /// Generates expression reading one pixel encoded in given format from input buffer (with bytes ordered accordingly to endianess) at given position 
        /// and storing each channel in separate variable expression.
        /// </summary>
        /// <returns>Generated expression.</returns>
        /// <param name="inputBufferDescriptor">Object containing information about input buffer: color format and endianness.</param>
        /// <param name="inBuffer">Input buffer.</param>
        /// <param name="clutBuffer">Color look-up table buffer.</param>
        /// <param name="inPosition">Position of pixel in buffer.</param>
        /// <param name="color">Variable where values of color channels should be stored.</param>
        private static Expression GenerateFrom(BufferDescriptor inputBufferDescriptor, ParameterExpression inBuffer, ParameterExpression clutBuffer, Expression inPosition, PixelDescriptor color, Expression tmp)
        {
            byte currentBit = 0;
            byte currentByte = 0;
            bool isAlphaSet = false;
            
            var expressions = new List<Expression>();
            var inputBytes = new ParameterExpression[inputBufferDescriptor.ColorFormat.GetColorDepth()];
            for(int i = 0; i < inputBytes.Length; i++)
            {
                inputBytes[i] = Expression.Variable(typeof(uint));
                
                expressions.Add(
                    Expression.Assign(
                        inputBytes[i], 
                        Expression.Convert(
                            Expression.ArrayIndex(
                                inBuffer,
                                Expression.Add(
                                    inPosition, 
                                    Expression.Constant((inputBufferDescriptor.DataEndianness == Endianess.BigEndian) ? i : inputBytes.Length - i - 1))),
                            typeof(uint))));
            }

            foreach(var colorDescriptor in inputBufferDescriptor.ColorFormat.GetColorsLengths())
            {
                Expression colorExpression = null; 
                
                foreach(var transformation in ByteInflate(colorDescriptor.Value, currentBit))
                {
                    Expression currentExpressionFragment = inputBytes[currentByte];
                    
                    if(transformation.MaskBits != 0xFF)
                    {
                        currentExpressionFragment = Expression.And(currentExpressionFragment, Expression.Constant((uint)transformation.MaskBits));
                    }
                    
                    if(transformation.ShiftBits > 0)
                    {
                        currentExpressionFragment = Expression.RightShift(currentExpressionFragment, Expression.Constant((int)transformation.ShiftBits));
                    }
                    else if(transformation.ShiftBits < 0)
                    {
                        currentExpressionFragment = Expression.And(
                            Expression.LeftShift(currentExpressionFragment, Expression.Constant((int)(-transformation.ShiftBits))),
                            Expression.Constant((uint)0xFF));
                    }
                    
                    currentBit += transformation.UsedBits;
                    if(currentBit >= 8)
                    {
                        currentBit -= 8;
                        currentByte++;
                    }
                    
                    colorExpression = (colorExpression == null) ? currentExpressionFragment : Expression.Or(colorExpression, currentExpressionFragment);
                }

                if(colorDescriptor.Key == ColorType.X)
                {
                    continue;
                }

                // luminance - indirect color indexing using CLUT
                if(colorDescriptor.Key == ColorType.L)
                {
                    if(!inputBufferDescriptor.ClutColorFormat.HasValue)
                    {
                        throw new ArgumentException("CLUT mode required but not set");
                    }

                    var clutWidth = Expression.Constant((uint)inputBufferDescriptor.ClutColorFormat.Value.GetColorDepth());
                    var clutOffset = Expression.Multiply(colorExpression, clutWidth);

                    expressions.Add(Expression.Assign(tmp, color.AlphaChannel));

                    // todo: indirect parameters should not be needed here, but we  m u s t  pass something
                    expressions.Add(
                        GenerateFrom(new BufferDescriptor
                    { 
                        ColorFormat = inputBufferDescriptor.ClutColorFormat.Value, 
                        DataEndianness = inputBufferDescriptor.DataEndianness 
                    }, clutBuffer, clutBuffer, Expression.Convert(clutOffset, typeof(int)), color, tmp));

                    expressions.Add(Expression.Assign(color.AlphaChannel, tmp));
                }
                else
                {
                    Expression currentColor = null;
                    switch(colorDescriptor.Key)
                    {
                    case ColorType.A:
                        currentColor = color.AlphaChannel;
                        isAlphaSet = true;
                        break;
                    case ColorType.B:
                        currentColor = color.BlueChannel;
                        break;
                    case ColorType.G:
                        currentColor = color.GreenChannel;
                        break;
                    case ColorType.R:
                        currentColor = color.RedChannel;
                        break;
                    }

                    expressions.Add(Expression.Assign(currentColor, colorExpression));
                                
                    // filling lsb '0'-bits with copy of msb pattern
                    var numberOfBits = colorDescriptor.Value;
                    var zeroBits = 8 - numberOfBits;
                    while(zeroBits > 0)
                    {
                        expressions.Add(Expression.OrAssign(
                            currentColor, 
                            Expression.RightShift(
                                currentColor, 
                                Expression.Constant((int)numberOfBits))));
                        zeroBits -= numberOfBits;
                    }
                }
            }

            if(!isAlphaSet)
            {
                expressions.Add(Expression.Assign(color.AlphaChannel, Expression.Constant((uint)0xFF)));
            }
            return Expression.Block(inputBytes, expressions);
        }
Example #9
0
        public void Run()
        {
            try
            {
                // Load renderer
                renderer = RenderSystem.Load("OpenGL", debugger);

                // Create render context
                var contextDesc = new RenderContextDescriptor();
                {
                    contextDesc.VideoMode.Resolution.Width   = 800;
                    contextDesc.VideoMode.Resolution.Height  = 600;
                    contextDesc.VideoMode.ColorBits          = 32;
                    contextDesc.VideoMode.DepthBits          = 24;
                    contextDesc.VideoMode.StencilBits        = 8;
                    contextDesc.ProfileOpenGL.ContextProfile = OpenGLContextProfile.CoreProfile;
                }
                context = renderer.CreateRenderContext(contextDesc);

                // Get context window
                var window = context.Surface;
                window.Shown = true;

                window.Title = $"LLGL for C# - HelloTriangle ( {renderer.Name} )";

                // Print renderer information
                Console.WriteLine("Renderer Info:");
                var info = renderer.Info;
                {
                    Console.WriteLine($"  Renderer:         {info.RendererName}");
                    Console.WriteLine($"  Device:           {info.DeviceName}");
                    Console.WriteLine($"  Vendor:           {info.VendorName}");
                    Console.WriteLine($"  Shading Language: {info.ShadingLanguageName}");
                }

                // Create vertex buffer
                var vertexFormat = new VertexFormat();
                vertexFormat.AppendAttribute(new VertexAttribute("coord", Format.RGBA32Float));
                vertexFormat.AppendAttribute(new VertexAttribute("color", Format.RGBA8UNorm));

                var vertices = new Vertex[]
                {
                    new Vertex {
                        x = 0.0f, y = 0.5f, z = 0.0f, w = 1.0f, r = 255, g = 0, b = 0, a = 255
                    },
                    new Vertex {
                        x = 0.5f, y = -0.5f, z = 0.0f, w = 1.0f, r = 0, g = 255, b = 0, a = 255
                    },
                    new Vertex {
                        x = -0.5f, y = -0.5f, z = 0.0f, w = 1.0f, r = 0, g = 0, b = 255, a = 255
                    },
                };

                var vertexBufferDesc = new BufferDescriptor();
                {
                    vertexBufferDesc.Type = BufferType.Vertex;
                    vertexBufferDesc.Size = vertexFormat.Stride * (ulong)vertices.Length;
                    vertexBufferDesc.VertexBuffer.Format = vertexFormat;
                }
                var vertexBuffer = renderer.CreateBuffer(vertexBufferDesc, vertices);

                // Create shaders
                var vertShader = renderer.CreateShader(
                    new ShaderDescriptor(
                        type: ShaderType.Vertex,
                        sourceType: ShaderSourceType.CodeString,
                        source: @"
                            #version 330 core
                            in vec4 coord;
                            in vec3 color;
                            out vec4 vColor;
                            void main() {
                                gl_Position = coord;
                                vColor = vec4(color, 1);
                            }
                        "
                        )
                    );
                var fragShader = renderer.CreateShader(
                    new ShaderDescriptor
                    (
                        type: ShaderType.Fragment,
                        sourceType: ShaderSourceType.CodeString,
                        source: @"
                            #version 330 core
                            in vec4 vColor;
                            out vec4 fColor;
                            void main() {
                                fColor = vColor;
                            }
                        "
                    )
                    );

                var shaderProgramDesc = new ShaderProgramDescriptor();
                {
                    shaderProgramDesc.VertexFormats.Add(vertexFormat);
                    shaderProgramDesc.VertexShader   = vertShader;
                    shaderProgramDesc.FragmentShader = fragShader;
                }
                var shaderProgram = renderer.CreateShaderProgram(shaderProgramDesc);

                if (shaderProgram.HasErrors)
                {
                    throw new Exception(shaderProgram.QueryInfoLog());
                }

                // Create graphics pipeline
                var pipelineDesc = new GraphicsPipelineDescriptor();
                {
                    pipelineDesc.ShaderProgram = shaderProgram;
                }
                pipeline = renderer.CreateGraphicsPipeline(pipelineDesc);

                // Get command queue
                cmdQueue  = renderer.CommandQueue;
                cmdBuffer = renderer.CreateCommandBuffer();

                cmdBuffer.SetClearColor(0.1f, 0.1f, 0.2f, 1.0f);

                // Render loop
                while (window.ProcessEvents())
                {
                    cmdBuffer.Begin();
                    {
                        cmdBuffer.SetVertexBuffer(vertexBuffer);

                        cmdBuffer.BeginRenderPass(context);
                        {
                            cmdBuffer.Clear(ClearFlags.Color);
                            cmdBuffer.SetViewport(new Viewport(context.Resolution));

                            cmdBuffer.SetGraphicsPipeline(pipeline);

                            cmdBuffer.Draw(3, 0);
                        }
                        cmdBuffer.EndRenderPass();
                    }
                    cmdBuffer.End();
                    cmdQueue.Submit(cmdBuffer);

                    context.Present();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                Console.WriteLine("press any key to continue ...");
                Console.ReadKey();
            }
            finally
            {
                RenderSystem.Unload(renderer);
            }
        }
Example #10
0
        /// <summary>
        /// Performs the compute dispatch operation.
        /// </summary>
        /// <param name="argument">Method call argument</param>
        private void SendSignalingPcasB(int argument)
        {
            var memoryManager = _channel.MemoryManager;

            _3dEngine.FlushUboDirty();

            uint qmdAddress = _state.State.SendPcasA;

            var qmd = _channel.MemoryManager.Read <ComputeQmd>((ulong)qmdAddress << 8);

            ulong shaderGpuVa = ((ulong)_state.State.SetProgramRegionAAddressUpper << 32) | _state.State.SetProgramRegionB;

            shaderGpuVa += (uint)qmd.ProgramOffset;

            int localMemorySize = qmd.ShaderLocalMemoryLowSize + qmd.ShaderLocalMemoryHighSize;

            int sharedMemorySize = Math.Min(qmd.SharedMemorySize, _context.Capabilities.MaximumComputeSharedMemorySize);

            for (int index = 0; index < Constants.TotalCpUniformBuffers; index++)
            {
                if (!qmd.ConstantBufferValid(index))
                {
                    continue;
                }

                ulong gpuVa = (uint)qmd.ConstantBufferAddrLower(index) | (ulong)qmd.ConstantBufferAddrUpper(index) << 32;
                ulong size  = (ulong)qmd.ConstantBufferSize(index);

                _channel.BufferManager.SetComputeUniformBuffer(index, gpuVa, size);
            }

            ulong samplerPoolGpuVa = ((ulong)_state.State.SetTexSamplerPoolAOffsetUpper << 32) | _state.State.SetTexSamplerPoolB;
            ulong texturePoolGpuVa = ((ulong)_state.State.SetTexHeaderPoolAOffsetUpper << 32) | _state.State.SetTexHeaderPoolB;

            GpuAccessorState gas = new GpuAccessorState(
                texturePoolGpuVa,
                _state.State.SetTexHeaderPoolCMaximumIndex,
                _state.State.SetBindlessTextureConstantBufferSlotSelect,
                false,
                false,
                false,
                0f,
                PrimitiveTopology.Points);

            ShaderBundle cs = memoryManager.Physical.ShaderCache.GetComputeShader(
                _channel,
                gas,
                shaderGpuVa,
                qmd.CtaThreadDimension0,
                qmd.CtaThreadDimension1,
                qmd.CtaThreadDimension2,
                localMemorySize,
                sharedMemorySize);

            _context.Renderer.Pipeline.SetProgram(cs.HostProgram);

            _channel.TextureManager.SetComputeSamplerPool(samplerPoolGpuVa, _state.State.SetTexSamplerPoolCMaximumIndex, qmd.SamplerIndex);
            _channel.TextureManager.SetComputeTexturePool(texturePoolGpuVa, _state.State.SetTexHeaderPoolCMaximumIndex);
            _channel.TextureManager.SetComputeTextureBufferIndex(_state.State.SetBindlessTextureConstantBufferSlotSelect);

            ShaderProgramInfo info = cs.Shaders[0].Info;

            for (int index = 0; index < info.CBuffers.Count; index++)
            {
                BufferDescriptor cb = info.CBuffers[index];

                // NVN uses the "hardware" constant buffer for anything that is less than 8,
                // and those are already bound above.
                // Anything greater than or equal to 8 uses the emulated constant buffers.
                // They are emulated using global memory loads.
                if (cb.Slot < 8)
                {
                    continue;
                }

                ulong cbDescAddress = _channel.BufferManager.GetComputeUniformBufferAddress(0);

                int cbDescOffset = 0x260 + (cb.Slot - 8) * 0x10;

                cbDescAddress += (ulong)cbDescOffset;

                SbDescriptor cbDescriptor = _channel.MemoryManager.Physical.Read <SbDescriptor>(cbDescAddress);

                _channel.BufferManager.SetComputeUniformBuffer(cb.Slot, cbDescriptor.PackAddress(), (uint)cbDescriptor.Size);
            }

            for (int index = 0; index < info.SBuffers.Count; index++)
            {
                BufferDescriptor sb = info.SBuffers[index];

                ulong sbDescAddress = _channel.BufferManager.GetComputeUniformBufferAddress(0);

                int sbDescOffset = 0x310 + sb.Slot * 0x10;

                sbDescAddress += (ulong)sbDescOffset;

                SbDescriptor sbDescriptor = _channel.MemoryManager.Physical.Read <SbDescriptor>(sbDescAddress);

                _channel.BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size, sb.Flags);
            }

            _channel.BufferManager.SetComputeStorageBufferBindings(info.SBuffers);
            _channel.BufferManager.SetComputeUniformBufferBindings(info.CBuffers);

            var textureBindings = new TextureBindingInfo[info.Textures.Count];

            for (int index = 0; index < info.Textures.Count; index++)
            {
                var descriptor = info.Textures[index];

                Target target = ShaderTexture.GetTarget(descriptor.Type);

                textureBindings[index] = new TextureBindingInfo(
                    target,
                    descriptor.Binding,
                    descriptor.CbufSlot,
                    descriptor.HandleIndex,
                    descriptor.Flags);
            }

            _channel.TextureManager.SetComputeTextures(textureBindings);

            var imageBindings = new TextureBindingInfo[info.Images.Count];

            for (int index = 0; index < info.Images.Count; index++)
            {
                var descriptor = info.Images[index];

                Target target = ShaderTexture.GetTarget(descriptor.Type);
                Format format = ShaderTexture.GetFormat(descriptor.Format);

                imageBindings[index] = new TextureBindingInfo(
                    target,
                    format,
                    descriptor.Binding,
                    descriptor.CbufSlot,
                    descriptor.HandleIndex,
                    descriptor.Flags);
            }

            _channel.TextureManager.SetComputeImages(imageBindings);

            _channel.TextureManager.CommitComputeBindings();
            _channel.BufferManager.CommitComputeBindings();

            _context.Renderer.Pipeline.DispatchCompute(qmd.CtaRasterWidth, qmd.CtaRasterHeight, qmd.CtaRasterDepth);

            _3dEngine.ForceShaderUpdate();
        }
Example #11
0
        /// <summary>
        /// Dispatches compute work.
        /// </summary>
        /// <param name="state">Current GPU state</param>
        /// <param name="argument">Method call argument</param>
        public void Dispatch(GpuState state, int argument)
        {
            uint dispatchParamsAddress = (uint)state.Get <int>(MethodOffset.DispatchParamsAddress);

            var dispatchParams = _context.MemoryAccessor.Read <ComputeParams>((ulong)dispatchParamsAddress << 8);

            GpuVa shaderBaseAddress = state.Get <GpuVa>(MethodOffset.ShaderBaseAddress);

            ulong shaderGpuVa = shaderBaseAddress.Pack() + (uint)dispatchParams.ShaderOffset;

            // Note: A size of 0 is also invalid, the size must be at least 1.
            int sharedMemorySize = Math.Clamp(dispatchParams.SharedMemorySize & 0xffff, 1, _context.Capabilities.MaximumComputeSharedMemorySize);

            ComputeShader cs = ShaderCache.GetComputeShader(
                shaderGpuVa,
                sharedMemorySize,
                dispatchParams.UnpackBlockSizeX(),
                dispatchParams.UnpackBlockSizeY(),
                dispatchParams.UnpackBlockSizeZ());

            _context.Renderer.Pipeline.SetProgram(cs.HostProgram);

            var samplerPool = state.Get <PoolState>(MethodOffset.SamplerPoolState);

            TextureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId, dispatchParams.SamplerIndex);

            var texturePool = state.Get <PoolState>(MethodOffset.TexturePoolState);

            TextureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);

            TextureManager.SetComputeTextureBufferIndex(state.Get <int>(MethodOffset.TextureBufferIndex));

            ShaderProgramInfo info = cs.Shader.Program.Info;

            uint sbEnableMask = 0;
            uint ubEnableMask = dispatchParams.UnpackUniformBuffersEnableMask();

            for (int index = 0; index < dispatchParams.UniformBuffers.Length; index++)
            {
                if ((ubEnableMask & (1 << index)) == 0)
                {
                    continue;
                }

                ulong gpuVa = dispatchParams.UniformBuffers[index].PackAddress();
                ulong size  = dispatchParams.UniformBuffers[index].UnpackSize();

                BufferManager.SetComputeUniformBuffer(index, gpuVa, size);
            }

            for (int index = 0; index < info.SBuffers.Count; index++)
            {
                BufferDescriptor sb = info.SBuffers[index];

                sbEnableMask |= 1u << sb.Slot;

                ulong sbDescAddress = BufferManager.GetComputeUniformBufferAddress(0);

                int sbDescOffset = 0x310 + sb.Slot * 0x10;

                sbDescAddress += (ulong)sbDescOffset;

                ReadOnlySpan <byte> sbDescriptorData = _context.PhysicalMemory.GetSpan(sbDescAddress, 0x10);

                SbDescriptor sbDescriptor = MemoryMarshal.Cast <byte, SbDescriptor>(sbDescriptorData)[0];

                BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size);
            }

            ubEnableMask = 0;

            for (int index = 0; index < info.CBuffers.Count; index++)
            {
                ubEnableMask |= 1u << info.CBuffers[index].Slot;
            }

            BufferManager.SetComputeStorageBufferEnableMask(sbEnableMask);
            BufferManager.SetComputeUniformBufferEnableMask(ubEnableMask);

            var textureBindings = new TextureBindingInfo[info.Textures.Count];

            for (int index = 0; index < info.Textures.Count; index++)
            {
                var descriptor = info.Textures[index];

                Target target = GetTarget(descriptor.Type);

                if (descriptor.IsBindless)
                {
                    textureBindings[index] = new TextureBindingInfo(target, descriptor.CbufOffset, descriptor.CbufSlot);
                }
                else
                {
                    textureBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
                }
            }

            TextureManager.SetComputeTextures(textureBindings);

            var imageBindings = new TextureBindingInfo[info.Images.Count];

            for (int index = 0; index < info.Images.Count; index++)
            {
                var descriptor = info.Images[index];

                Target target = GetTarget(descriptor.Type);

                imageBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
            }

            TextureManager.SetComputeImages(imageBindings);

            BufferManager.CommitComputeBindings();
            TextureManager.CommitComputeBindings();

            _context.Renderer.Pipeline.DispatchCompute(
                dispatchParams.UnpackGridSizeX(),
                dispatchParams.UnpackGridSizeY(),
                dispatchParams.UnpackGridSizeZ());

            UpdateShaderState(state);
        }
Example #12
0
        private static BlendDelegate GenerateBlendMethod(BufferDescriptor backgroudBufferDescriptor, BufferDescriptor foregroundBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var outputPixel = new PixelDescriptor();
            var inputBackgroundPixel = new PixelDescriptor();
            var inputForegroundPixel = new PixelDescriptor();
            var contantBackgroundPixel = new PixelDescriptor();

            var vBackPos = Expression.Variable(typeof(int), "backPos");
            var vFrontPos = Expression.Variable(typeof(int), "frontPos");
            var vOutPos = Expression.Variable(typeof(int), "outPos");
            var vBackStep = Expression.Variable(typeof(int), "backStep");
            var vFrontStep = Expression.Variable(typeof(int), "frontStep");
            var vOutStep = Expression.Variable(typeof(int), "outStep");
            var vLength = Expression.Variable(typeof(int),  "length");

            var vBackBuffer = Expression.Parameter(typeof(byte[]), "backBuffer");
            var vBackClutBuffer = Expression.Parameter(typeof(byte[]), "backClutBuffer");
            var vFrontBuffer = Expression.Parameter(typeof(byte[]), "fronBuffer");
            var vFrontClutBuffer = Expression.Parameter(typeof(byte[]), "frontClutBuffer");
            var vOutputBuffer = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");
            var vBackgroundColor = Expression.Parameter(typeof(Pixel), "backgroundColor");
            var vBackBufferAlphaMultiplier = Expression.Parameter(typeof(byte), "backBufferAlphaMultiplier");
            var vFrontBufferAlphaMultiplier = Expression.Parameter(typeof(byte), "frontBufferAlphaMultiplier");

            var vBackAlphaBlended = Expression.Variable(typeof(uint), "backAlphaBlended");
            var vBackgroundColorAlphaBlended = Expression.Variable(typeof(uint), "backgroundColorAlphaBlended");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new[] {  outputPixel.RedChannel, outputPixel.GreenChannel, outputPixel.BlueChannel, outputPixel.AlphaChannel,
                         inputForegroundPixel.RedChannel, inputForegroundPixel.GreenChannel, inputForegroundPixel.BlueChannel, inputForegroundPixel.AlphaChannel,
                         inputBackgroundPixel.RedChannel, inputBackgroundPixel.GreenChannel, inputBackgroundPixel.BlueChannel, inputBackgroundPixel.AlphaChannel,
                         vBackStep, vFrontStep, vOutStep, vLength, vBackPos, vFrontPos, vOutPos,
                         contantBackgroundPixel.RedChannel, contantBackgroundPixel.GreenChannel, contantBackgroundPixel.BlueChannel, contantBackgroundPixel.AlphaChannel,
                         vBackAlphaBlended, vBackgroundColorAlphaBlended,
                                    tmp
                },

                Expression.Assign(vBackStep, Expression.Constant(backgroudBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vFrontStep, Expression.Constant(foregroundBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vBackBuffer, "Length")),

                Expression.Assign(vBackPos, Expression.Constant(0x00)),
                Expression.Assign(vFrontPos, Expression.Constant(0x00)),
                Expression.Assign(vOutPos, Expression.Constant(0x00)),

                Expression.Assign(contantBackgroundPixel.AlphaChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Alpha"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.RedChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Red"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.GreenChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Green"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.BlueChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Blue"), typeof(uint))),

                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vBackPos, vLength),
                        Expression.Block(

                            GenerateFrom(backgroudBufferDescriptor, vBackBuffer, vBackClutBuffer, vBackPos, inputBackgroundPixel, tmp),
                            GenerateFrom(foregroundBufferDescriptor, vFrontBuffer, vFrontClutBuffer, vFrontPos, inputForegroundPixel, tmp),

                            Expression.Assign(inputBackgroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputBackgroundPixel.AlphaChannel, Expression.Convert(vBackBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),
                            Expression.Assign(inputForegroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputForegroundPixel.AlphaChannel, Expression.Convert(vFrontBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),

                            Expression.Block(
                                // (b_alpha * (0xFF - f_alpha)) / 0xFF
                                Expression.Assign(
                                    vBackAlphaBlended,
                                    Expression.Divide(
                                        Expression.Multiply(
                                            inputBackgroundPixel.AlphaChannel,
                                            Expression.Subtract(
                                                Expression.Constant((uint)0xFF),
                                                inputForegroundPixel.AlphaChannel)),
                                        Expression.Constant((uint)0xFF))),

                                // (c_alpha * (0xFF - (f_alpha + b_alpha * (0xFF - f_alpha)))) / 0xFF
                                Expression.Assign(
                                        vBackgroundColorAlphaBlended,
                                        Expression.Divide(
                                            Expression.Multiply(
                                                contantBackgroundPixel.AlphaChannel,
                                                Expression.Subtract(
                                                    Expression.Constant((uint)0xFF),
                                                    Expression.Add(
                                                        inputForegroundPixel.AlphaChannel,
                                                        vBackAlphaBlended))),
                                             Expression.Constant((uint)0xFF))),
                                                  
                                Expression.Assign(
                                    outputPixel.AlphaChannel, 
                                    Expression.Add(
                                        inputForegroundPixel.AlphaChannel,
                                        Expression.Add(
                                            vBackAlphaBlended,
                                            vBackgroundColorAlphaBlended))),

                                Expression.IfThenElse(
                                    Expression.Equal(outputPixel.AlphaChannel, Expression.Constant((uint)0)),
                                    Expression.Block(
                                        Expression.Assign(outputPixel.RedChannel, contantBackgroundPixel.RedChannel),
                                        Expression.Assign(outputPixel.GreenChannel, contantBackgroundPixel.GreenChannel),
                                        Expression.Assign(outputPixel.BlueChannel, contantBackgroundPixel.BlueChannel),
                                        Expression.Assign(outputPixel.AlphaChannel, contantBackgroundPixel.AlphaChannel)),
                                    Expression.Block( 
                                        Expression.Assign(
                                            outputPixel.RedChannel, 
                                            Expression.Divide(
                                                Expression.Add(
                                                    Expression.Add(
                                                        Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.RedChannel),
                                                        Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.RedChannel)),
                                                    Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.RedChannel)),
                                                outputPixel.AlphaChannel)),
                                        Expression.Assign(
                                            outputPixel.GreenChannel, 
                                            Expression.Divide(
                                                Expression.Add(
                                                    Expression.Add(
                                                        Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.GreenChannel),
                                                        Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.GreenChannel)),
                                                    Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.GreenChannel)),
                                                outputPixel.AlphaChannel)),
                                        Expression.Assign(
                                            outputPixel.BlueChannel, 
                                            Expression.Divide(
                                                Expression.Add(
                                                    Expression.Add(
                                                        Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.BlueChannel),
                                                        Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.BlueChannel)),
                                                    Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.BlueChannel)),
                                                outputPixel.AlphaChannel))))
                            ),

                            GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, outputPixel),

                            Expression.AddAssign(vBackPos, vBackStep),
                            Expression.AddAssign(vFrontPos, vFrontStep),
                            Expression.AddAssign(vOutPos, vOutStep)
                        ),
                        Expression.Break(outOfLoop)
                    ),
                    outOfLoop
                )
            );

            return Expression.Lambda<BlendDelegate>(block, vBackBuffer, vBackClutBuffer, vFrontBuffer, vFrontClutBuffer, vOutputBuffer, vBackgroundColor, vBackBufferAlphaMultiplier, vFrontBufferAlphaMultiplier).Compile();
        }
Example #13
0
        /// <summary>
        /// Generates expression converting and storing one pixel in output format to output buffer (ordering bytes accordingly to endianess) at given position using channels values provided by red/green/blue/alpha variables.
        /// </summary>
        /// <returns>Generated expression.</returns>
        /// <param name="outputBufferDescriptor">Object containing information about output buffer: color format and endianness.</param>
        /// <param name="outBuffer">Output buffer.</param>
        /// <param name="outPosition">Position of pixel in output buffer.</param>
        /// <param name="color">Object with variables from which value of color channels should be read.</param>
        private static Expression GenerateTo(BufferDescriptor outputBufferDescriptor, ParameterExpression outBuffer, ParameterExpression outPosition, PixelDescriptor color)
        {
            byte currentBit = 0;
            byte currentByte = 0;
            var expressions = new List<Expression>();
            
            Expression currentExpression = null;
            
            foreach(var colorDescriptor in outputBufferDescriptor.ColorFormat.GetColorsLengths())
            {
                Expression colorExpression = null; 
                
                switch(colorDescriptor.Key)
                {
                case ColorType.A:
                    colorExpression = color.AlphaChannel;
                    break;
                case ColorType.B:
                    colorExpression = color.BlueChannel;
                    break;
                case ColorType.G:
                    colorExpression = color.GreenChannel;
                    break;
                case ColorType.R:
                    colorExpression = color.RedChannel;
                    break;
                case ColorType.X:
                    colorExpression = Expression.Constant((uint)0xFF);
                    break;
                case ColorType.L:
                    throw new ArgumentException("Luminance channel is not allowed in target color format");
                }

                foreach(var transformation in ByteSqueezeAndMove(colorDescriptor.Value, currentBit))
                {
                    Expression currentExpressionFragment = colorExpression;
                
                    if(transformation.MaskBits != 0xFF)
                    {
                        currentExpressionFragment = Expression.And(currentExpressionFragment, Expression.Constant((uint)transformation.MaskBits));
                    }

                    if(transformation.ShiftBits > 0)
                    {
                        currentExpressionFragment = Expression.RightShift(currentExpressionFragment, Expression.Constant((int)transformation.ShiftBits));
                    }
                    else if(transformation.ShiftBits < 0)
                    {
                        currentExpressionFragment = Expression.And(
                            Expression.LeftShift(currentExpressionFragment, Expression.Constant((int)(-transformation.ShiftBits))),
                            Expression.Constant((uint)0xFF));
                                
                    }
                    
                    currentExpression = (currentExpression == null) ? currentExpressionFragment : Expression.Or(currentExpression, currentExpressionFragment);

                    currentBit += transformation.UsedBits;
                    while(currentBit >= 8)
                    {
                        expressions.Add(
                            Expression.Assign(
                                Expression.ArrayAccess(outBuffer, 
                                    Expression.Add(
                                        outPosition, 
                                        Expression.Constant((outputBufferDescriptor.DataEndianness == Endianess.BigEndian) ? (int) currentByte : (outputBufferDescriptor.ColorFormat.GetColorDepth() - currentByte - 1)))),
                                Expression.Convert(currentExpression, typeof(byte))));

                        currentExpression = null;
                        currentBit -= 8;
                        currentByte++;
                    }
                }
            }

            return Expression.Block(expressions);
        }
Example #14
0
        /// <summary>
        /// Dispatches compute work.
        /// </summary>
        /// <param name="state">Current GPU state</param>
        /// <param name="argument">Method call argument</param>
        public void Dispatch(GpuState state, int argument)
        {
            uint qmdAddress = (uint)state.Get <int>(MethodOffset.DispatchParamsAddress);

            var qmd = _context.MemoryManager.Read <ComputeQmd>((ulong)qmdAddress << 8);

            GpuVa shaderBaseAddress = state.Get <GpuVa>(MethodOffset.ShaderBaseAddress);

            ulong shaderGpuVa = shaderBaseAddress.Pack() + (uint)qmd.ProgramOffset;

            int localMemorySize = qmd.ShaderLocalMemoryLowSize + qmd.ShaderLocalMemoryHighSize;

            int sharedMemorySize = Math.Min(qmd.SharedMemorySize, _context.Capabilities.MaximumComputeSharedMemorySize);

            for (int index = 0; index < Constants.TotalCpUniformBuffers; index++)
            {
                if (!qmd.ConstantBufferValid(index))
                {
                    continue;
                }

                ulong gpuVa = (uint)qmd.ConstantBufferAddrLower(index) | (ulong)qmd.ConstantBufferAddrUpper(index) << 32;
                ulong size  = (ulong)qmd.ConstantBufferSize(index);

                BufferManager.SetComputeUniformBuffer(index, gpuVa, size);
            }

            ShaderBundle cs = ShaderCache.GetComputeShader(
                state,
                shaderGpuVa,
                qmd.CtaThreadDimension0,
                qmd.CtaThreadDimension1,
                qmd.CtaThreadDimension2,
                localMemorySize,
                sharedMemorySize);

            _context.Renderer.Pipeline.SetProgram(cs.HostProgram);

            var samplerPool = state.Get <PoolState>(MethodOffset.SamplerPoolState);
            var texturePool = state.Get <PoolState>(MethodOffset.TexturePoolState);

            TextureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId, qmd.SamplerIndex);
            TextureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
            TextureManager.SetComputeTextureBufferIndex(state.Get <int>(MethodOffset.TextureBufferIndex));

            ShaderProgramInfo info = cs.Shaders[0].Program.Info;

            for (int index = 0; index < info.CBuffers.Count; index++)
            {
                BufferDescriptor cb = info.CBuffers[index];

                // NVN uses the "hardware" constant buffer for anything that is less than 8,
                // and those are already bound above.
                // Anything greater than or equal to 8 uses the emulated constant buffers.
                // They are emulated using global memory loads.
                if (cb.Slot < 8)
                {
                    continue;
                }

                ulong cbDescAddress = BufferManager.GetComputeUniformBufferAddress(0);

                int cbDescOffset = 0x260 + (cb.Slot - 8) * 0x10;

                cbDescAddress += (ulong)cbDescOffset;

                SbDescriptor cbDescriptor = _context.PhysicalMemory.Read <SbDescriptor>(cbDescAddress);

                BufferManager.SetComputeUniformBuffer(cb.Slot, cbDescriptor.PackAddress(), (uint)cbDescriptor.Size);
            }

            for (int index = 0; index < info.SBuffers.Count; index++)
            {
                BufferDescriptor sb = info.SBuffers[index];

                ulong sbDescAddress = BufferManager.GetComputeUniformBufferAddress(0);

                int sbDescOffset = 0x310 + sb.Slot * 0x10;

                sbDescAddress += (ulong)sbDescOffset;

                SbDescriptor sbDescriptor = _context.PhysicalMemory.Read <SbDescriptor>(sbDescAddress);

                BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size);
            }

            BufferManager.SetComputeStorageBufferBindings(info.SBuffers);
            BufferManager.SetComputeUniformBufferBindings(info.CBuffers);

            var textureBindings = new TextureBindingInfo[info.Textures.Count];

            for (int index = 0; index < info.Textures.Count; index++)
            {
                var descriptor = info.Textures[index];

                Target target = ShaderTexture.GetTarget(descriptor.Type);

                textureBindings[index] = new TextureBindingInfo(
                    target,
                    descriptor.Binding,
                    descriptor.CbufSlot,
                    descriptor.HandleIndex,
                    descriptor.Flags);
            }

            TextureManager.SetComputeTextures(textureBindings);

            var imageBindings = new TextureBindingInfo[info.Images.Count];

            for (int index = 0; index < info.Images.Count; index++)
            {
                var descriptor = info.Images[index];

                Target target = ShaderTexture.GetTarget(descriptor.Type);
                Format format = ShaderTexture.GetFormat(descriptor.Format);

                imageBindings[index] = new TextureBindingInfo(
                    target,
                    format,
                    descriptor.Binding,
                    descriptor.CbufSlot,
                    descriptor.HandleIndex,
                    descriptor.Flags);
            }

            TextureManager.SetComputeImages(imageBindings);

            BufferManager.CommitComputeBindings();
            TextureManager.CommitComputeBindings();

            _context.Renderer.Pipeline.DispatchCompute(
                qmd.CtaRasterWidth,
                qmd.CtaRasterHeight,
                qmd.CtaRasterDepth);

            _forceShaderUpdate = true;
        }
        private static BlendDelegate GenerateBlendMethod(BufferDescriptor backgroudBufferDescriptor, BufferDescriptor foregroundBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var outputPixel            = new PixelDescriptor();
            var inputBackgroundPixel   = new PixelDescriptor();
            var inputForegroundPixel   = new PixelDescriptor();
            var contantBackgroundPixel = new PixelDescriptor();

            var vBackPos   = Expression.Variable(typeof(int), "backPos");
            var vFrontPos  = Expression.Variable(typeof(int), "frontPos");
            var vOutPos    = Expression.Variable(typeof(int), "outPos");
            var vBackStep  = Expression.Variable(typeof(int), "backStep");
            var vFrontStep = Expression.Variable(typeof(int), "frontStep");
            var vOutStep   = Expression.Variable(typeof(int), "outStep");
            var vLength    = Expression.Variable(typeof(int), "length");

            var vBackBuffer                 = Expression.Parameter(typeof(byte[]), "backBuffer");
            var vBackClutBuffer             = Expression.Parameter(typeof(byte[]), "backClutBuffer");
            var vFrontBuffer                = Expression.Parameter(typeof(byte[]), "frontBuffer");
            var vFrontClutBuffer            = Expression.Parameter(typeof(byte[]), "frontClutBuffer");
            var vOutputBuffer               = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");
            var vBackgroundColor            = Expression.Parameter(typeof(Pixel), "backgroundColor");
            var vBackBufferAlphaMultiplier  = Expression.Parameter(typeof(byte), "backBufferAlphaMultiplier");
            var vFrontBufferAlphaMultiplier = Expression.Parameter(typeof(byte), "frontBufferAlphaMultiplier");

            var vBackgroundBlendingMode = Expression.Parameter(typeof(PixelBlendingMode), "backgroundBlendingMode");
            var vForegroundBlendingMode = Expression.Parameter(typeof(PixelBlendingMode), "foregroundBlendingMode");

            var vBackAlphaBlended            = Expression.Variable(typeof(uint), "backAlphaBlended");
            var vBackgroundColorAlphaBlended = Expression.Variable(typeof(uint), "backgroundColorAlphaBlended");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new[] { outputPixel.RedChannel, outputPixel.GreenChannel, outputPixel.BlueChannel, outputPixel.AlphaChannel,
                        inputForegroundPixel.RedChannel, inputForegroundPixel.GreenChannel, inputForegroundPixel.BlueChannel, inputForegroundPixel.AlphaChannel,
                        inputBackgroundPixel.RedChannel, inputBackgroundPixel.GreenChannel, inputBackgroundPixel.BlueChannel, inputBackgroundPixel.AlphaChannel,
                        vBackStep, vFrontStep, vOutStep, vLength, vBackPos, vFrontPos, vOutPos,
                        contantBackgroundPixel.RedChannel, contantBackgroundPixel.GreenChannel, contantBackgroundPixel.BlueChannel, contantBackgroundPixel.AlphaChannel,
                        vBackAlphaBlended, vBackgroundColorAlphaBlended,
                        tmp },

                Expression.Assign(vBackStep, Expression.Constant(backgroudBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vFrontStep, Expression.Constant(foregroundBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vBackBuffer, "Length")),

                Expression.Assign(vBackPos, Expression.Constant(0x00)),
                Expression.Assign(vFrontPos, Expression.Constant(0x00)),
                Expression.Assign(vOutPos, Expression.Constant(0x00)),

                Expression.Assign(contantBackgroundPixel.AlphaChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Alpha"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.RedChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Red"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.GreenChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Green"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.BlueChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Blue"), typeof(uint))),

                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vBackPos, vLength),
                                          Expression.Block(

                                              GenerateFrom(backgroudBufferDescriptor, vBackBuffer, vBackClutBuffer, vBackPos, inputBackgroundPixel, tmp),
                                              GenerateFrom(foregroundBufferDescriptor, vFrontBuffer, vFrontClutBuffer, vFrontPos, inputForegroundPixel, tmp),

                                              Expression.Switch(typeof(void), vBackgroundBlendingMode, null, null, new SwitchCase[]
            {
                // Multiply: input BG Pixel Alpha *= bg alpha
                Expression.SwitchCase(
                    Expression.Assign(inputBackgroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputBackgroundPixel.AlphaChannel, Expression.Convert(vBackBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),
                    Expression.Constant(PixelBlendingMode.Multiply)
                    ),

                // Replace: input BG Pixel Alpha = bg alpha
                Expression.SwitchCase(
                    Expression.Assign(inputBackgroundPixel.AlphaChannel, Expression.Convert(vBackBufferAlphaMultiplier, typeof(uint))),
                    Expression.Constant(PixelBlendingMode.Replace)
                    )
            }),

                                              Expression.Switch(typeof(void), vForegroundBlendingMode, null, null, new SwitchCase[]
            {
                // Multiply: input FG Pixel Alpha *= fg alpha
                Expression.SwitchCase(
                    Expression.Assign(inputForegroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputForegroundPixel.AlphaChannel, Expression.Convert(vFrontBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),
                    Expression.Constant(PixelBlendingMode.Multiply)
                    ),

                // Replace: input FG Pixel Alpha = fg alpha
                Expression.SwitchCase(
                    Expression.Assign(inputForegroundPixel.AlphaChannel, Expression.Convert(vFrontBufferAlphaMultiplier, typeof(uint))),
                    Expression.Constant(PixelBlendingMode.Replace)
                    )
            }),

                                              Expression.Block(
                                                  // (b_alpha * (0xFF - f_alpha)) / 0xFF
                                                  Expression.Assign(
                                                      vBackAlphaBlended,
                                                      Expression.Divide(
                                                          Expression.Multiply(
                                                              inputBackgroundPixel.AlphaChannel,
                                                              Expression.Subtract(
                                                                  Expression.Constant((uint)0xFF),
                                                                  inputForegroundPixel.AlphaChannel)),
                                                          Expression.Constant((uint)0xFF))),

                                                  // (c_alpha * (0xFF - (f_alpha + b_alpha * (0xFF - f_alpha)))) / 0xFF
                                                  Expression.Assign(
                                                      vBackgroundColorAlphaBlended,
                                                      Expression.Divide(
                                                          Expression.Multiply(
                                                              contantBackgroundPixel.AlphaChannel,
                                                              Expression.Subtract(
                                                                  Expression.Constant((uint)0xFF),
                                                                  Expression.Add(
                                                                      inputForegroundPixel.AlphaChannel,
                                                                      vBackAlphaBlended))),
                                                          Expression.Constant((uint)0xFF))),

                                                  Expression.Assign(
                                                      outputPixel.AlphaChannel,
                                                      Expression.Add(
                                                          inputForegroundPixel.AlphaChannel,
                                                          Expression.Add(
                                                              vBackAlphaBlended,
                                                              vBackgroundColorAlphaBlended))),

                                                  Expression.IfThenElse(
                                                      // If output pixel is 100% transparent
                                                      Expression.Equal(outputPixel.AlphaChannel, Expression.Constant((uint)0)),
                                                      // ... then the outputpixel should actually be equal to the underlying background pixel
                                                      Expression.Block(
                                                          Expression.Assign(outputPixel.RedChannel, contantBackgroundPixel.RedChannel),
                                                          Expression.Assign(outputPixel.GreenChannel, contantBackgroundPixel.GreenChannel),
                                                          Expression.Assign(outputPixel.BlueChannel, contantBackgroundPixel.BlueChannel),
                                                          Expression.Assign(outputPixel.AlphaChannel, contantBackgroundPixel.AlphaChannel)),
                                                      // ... else, apply alpha to all color channels
                                                      Expression.Block(
                                                          Expression.Assign(
                                                              outputPixel.RedChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.RedChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.RedChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.RedChannel)),
                                                                  outputPixel.AlphaChannel)),
                                                          Expression.Assign(
                                                              outputPixel.GreenChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.GreenChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.GreenChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.GreenChannel)),
                                                                  outputPixel.AlphaChannel)),
                                                          Expression.Assign(
                                                              outputPixel.BlueChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.BlueChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.BlueChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.BlueChannel)),
                                                                  outputPixel.AlphaChannel))))
                                                  ),

                                              GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, outputPixel),

                                              Expression.AddAssign(vBackPos, vBackStep),
                                              Expression.AddAssign(vFrontPos, vFrontStep),
                                              Expression.AddAssign(vOutPos, vOutStep)
                                              ),
                                          Expression.Break(outOfLoop)
                                          ),
                    outOfLoop
                    )
                );

            return(Expression.Lambda <BlendDelegate>(block, vBackBuffer, vBackClutBuffer, vFrontBuffer, vFrontClutBuffer, vOutputBuffer, vBackgroundColor, vBackBufferAlphaMultiplier, vBackgroundBlendingMode, vFrontBufferAlphaMultiplier, vForegroundBlendingMode).Compile());
        }
Example #16
0
 /// <summary>
 /// Creates a new instance of the shader stage buffer information.
 /// </summary>
 /// <param name="count">Maximum amount of buffers that the shader stage can use</param>
 public BuffersPerStage(int count)
 {
     Bindings = new BufferDescriptor[count];
     Buffers  = new BufferBounds[count];
 }
Example #17
0
        private static ConvertDelegate GenerateConvertMethod(BufferDescriptor inputBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var vColor = new PixelDescriptor();

            var vInStep = Expression.Variable(typeof(int),  "inStep");
            var vOutStep = Expression.Variable(typeof(int), "outStep");
            var vLength = Expression.Variable(typeof(int),  "length");

            var vInputBuffer = Expression.Parameter(typeof(byte[]), "inputBuffer");
            var vClutBuffer = Expression.Parameter(typeof(byte[]), "clutBuffer");
            var vOutputBuffer = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");

            var vInPos = Expression.Variable(typeof(int), "inPos");
            var vOutPos = Expression.Variable(typeof(int), "outPos");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new [] { vColor.RedChannel, vColor.GreenChannel, vColor.BlueChannel, vColor.AlphaChannel, vInStep, vOutStep, vLength, vInPos, vOutPos, tmp },

                Expression.Assign(vInStep, Expression.Constant(inputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vInputBuffer, "Length")),

                Expression.Assign(vInPos, Expression.Constant(0)),
                Expression.Assign(vOutPos, Expression.Constant(0)),
                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vInPos, vLength),
                        Expression.Block(
                            GenerateFrom(inputBufferDescriptor, vInputBuffer, vClutBuffer, vInPos, vColor, tmp),
                            GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, vColor),

                            Expression.AddAssign(vInPos, vInStep),
                            Expression.AddAssign(vOutPos, vOutStep)
                        ),
                        Expression.Break(outOfLoop)
                    ),
                    outOfLoop
                )
            );

            return Expression.Lambda<ConvertDelegate>(block, vInputBuffer, vClutBuffer, vOutputBuffer).Compile();
        }