Exemple #1
0
 protected Texture GetReadback(Texture texture)
 {
     if ((texture.Usage & TextureUsage.Staging) != 0)
     {
         return(texture);
     }
     else
     {
         uint layers = texture.ArrayLayers;
         if ((texture.Usage & TextureUsage.Cubemap) != 0)
         {
             layers *= 6;
         }
         TextureDescription desc = new TextureDescription(
             texture.Width, texture.Height, texture.Depth,
             texture.MipLevels, layers,
             texture.Format,
             TextureUsage.Staging, texture.Type);
         Texture     readback = RF.CreateTexture(ref desc);
         CommandList cl       = RF.CreateCommandList();
         cl.Begin();
         cl.CopyTexture(texture, readback);
         cl.End();
         GD.SubmitCommands(cl);
         GD.WaitForIdle();
         return(readback);
     }
 }
Exemple #2
0
        public Texture LoadTexture(Stream stream, bool staging)
        {
            using (stream)
            {
                Texture stagingTex = LoadStaging(stream);
                if (staging)
                {
                    return(stagingTex);
                }

                Texture sampledTex = _rf.CreateTexture(TextureDescription.Texture2D(
                                                           stagingTex.Width, stagingTex.Height, mipLevels: 1, arrayLayers: 1,
                                                           PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Sampled
                                                           ));

                using CommandList cl = _gd.ResourceFactory.CreateCommandList();
                cl.Begin();
                cl.CopyTexture(source: stagingTex, destination: sampledTex);
                cl.End();
                _gd.SubmitCommands(cl);
                // TODO: report the GL backend's quirk upstream
                if (_gd.BackendType == GraphicsBackend.OpenGL)
                {
                    _gd.DisposeWhenIdle(stagingTex);
                }
                else
                {
                    stagingTex.Dispose();
                }
                return(sampledTex);
            }
        }
Exemple #3
0
        public void NoDepthTarget_ClearAllColors_Succeeds()
        {
            Texture colorTarget = RF.CreateTexture(
                TextureDescription.Texture2D(1024, 1024, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget));
            Framebuffer fb = RF.CreateFramebuffer(new FramebufferDescription(null, colorTarget));

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.SetFramebuffer(fb);
            cl.ClearColorTarget(0, RgbaFloat.Red);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            Texture staging = RF.CreateTexture(
                TextureDescription.Texture2D(1024, 1024, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Staging));

            cl.Begin();
            cl.CopyTexture(
                colorTarget, 0, 0, 0, 0, 0,
                staging, 0, 0, 0, 0, 0,
                1024, 1024, 1, 1);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            MappedResourceView <RgbaFloat> view = GD.Map <RgbaFloat>(staging, MapMode.Read);

            for (int i = 0; i < view.Count; i++)
            {
                Assert.Equal(RgbaFloat.Red, view[i]);
            }
            GD.Unmap(staging);
        }
Exemple #4
0
        public unsafe void Update_ThenCopySingleMip_Succeeds_R16UNorm()
        {
            TextureDescription desc = TextureDescription.Texture2D(
                1024, 1024, 3, 1, PixelFormat.R16_UNorm, TextureUsage.Staging);
            Texture src = RF.CreateTexture(desc);
            Texture dst = RF.CreateTexture(desc);

            ushort[] data = Enumerable.Range(0, 256 * 256).Select(i => (ushort)i).ToArray();

            fixed(ushort *dataPtr = data)
            {
                GD.UpdateTexture(src, (IntPtr)dataPtr, 256 * 256 * sizeof(ushort), 0, 0, 0, 256, 256, 1, 2, 0);
            }

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.CopyTexture(src, dst, 2, 0);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            MappedResource map            = GD.Map(dst, MapMode.Read, 2);
            ushort *       mappedFloatPtr = (ushort *)map.Data;

            for (int y = 0; y < 256; y++)
            {
                for (int x = 0; x < 256; x++)
                {
                    uint   mapIndex = (uint)(y * (map.RowPitch / sizeof(ushort)) + x);
                    ushort value    = (ushort)(y * 256 + x);
                    Assert.Equal(value, mappedFloatPtr[mapIndex]);
                }
            }
        }
Exemple #5
0
        public unsafe Texture CreateDeviceTexture(GraphicsDevice gd, ResourceFactory rf, TextureUsage usage)
        {
            using (Texture staging = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels,
                                                                             ArrayLayers, Format, TextureUsage.Staging, Type)))
            {
                staging.Name = Name + "_Staging";

                fixed(uint *texDataPtr = &TextureData[0])
                {
                    uint subresourceSize = Width * Height * 4;

                    gd.UpdateTexture(
                        staging, (IntPtr)texDataPtr, subresourceSize,
                        0, 0, 0, Width, Height, 1, 0, 0);
                }

                Texture texture = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format, usage, Type));
                texture.Name = Name;
                using (CommandList cl = rf.CreateCommandList())
                {
                    cl.Begin();
                    cl.CopyTexture(staging, texture);
                    cl.End();
                    gd.SubmitCommands(cl);
                }

                IsDirty = false;
                return(texture);
            }
        }
        public void Render(CommandList cl, ISurfaceCopyStageModel stage, GpuSurface source)
        {
            if (cl == null || stage == null || source == null)
            {
                _frameworkMessenger.Report("Warning: you are feeding the Surface Copy Stage Renderer null inputs, aborting");
                return;
            }

            //Ensure the staging texture is of the correct size
            var stagingTexture = _gpuSurfaceManager.RetrieveSurface(stage.StagingTextureId);

            var doStagingTexturePropertiesMatch = source.Texture.Width == stagingTexture.Texture.Width &&
                                                  source.Texture.Height == stagingTexture.Texture.Height;

            var pixelFormatOfSource = source.Texture.Format;

            if (pixelFormatOfSource != stagingTexture.Texture.Format)
            {
                doStagingTexturePropertiesMatch = false;
            }

            if (!doStagingTexturePropertiesMatch)
            {
                stage.SetPixelFormatAndCreateStagingTextureAndDataArray(source.Texture.Width,
                                                                        source.Texture.Height,
                                                                        TexturePixelFormatConverter.ConvertVeldridToYak(pixelFormatOfSource));
                stagingTexture = _gpuSurfaceManager.RetrieveSurface(stage.StagingTextureId);
            }

            cl.CopyTexture(source.Texture, stagingTexture.Texture);
        }
Exemple #7
0
        public static unsafe Texture CreateSimpleTexture <T>(GraphicsDevice gd, TextureUsage usage, IReadOnlyTexture <T> texture) where T : unmanaged
        {
            if (gd == null)
            {
                throw new ArgumentNullException(nameof(gd));
            }
            if (texture == null)
            {
                throw new ArgumentNullException(nameof(texture));
            }

            var  pixelFormat = GetFormat(typeof(T));
            bool mip         = (usage & TextureUsage.GenerateMipmaps) != 0;
            uint mipLevels   = mip ? MipLevelCount(texture.Width, texture.Height) : 1;

            using Texture staging = gd.ResourceFactory.CreateTexture(new TextureDescription(
                                                                         (uint)texture.Width, (uint)texture.Height, 1,
                                                                         mipLevels,
                                                                         1,
                                                                         pixelFormat,
                                                                         TextureUsage.Staging,
                                                                         TextureType.Texture2D));

            staging.Name = "T_" + texture.Name + "_Staging";

            var buffer = texture.PixelData;

            fixed(T *texDataPtr = &buffer[0])
            {
                gd.UpdateTexture(
                    staging, (IntPtr)texDataPtr, (uint)(buffer.Length * Unsafe.SizeOf <T>()),
                    0, 0, 0,
                    (uint)texture.Width, (uint)texture.Height, 1,
                    0, 0);
            }

            Texture veldridTexture = gd.ResourceFactory.CreateTexture(new TextureDescription(
                                                                          (uint)texture.Width, (uint)texture.Height, 1,
                                                                          mipLevels,
                                                                          1,
                                                                          pixelFormat,
                                                                          usage,
                                                                          TextureType.Texture2D));

            veldridTexture.Name = "T_" + texture.Name;

            using CommandList cl = gd.ResourceFactory.CreateCommandList();
            cl.Begin();
            cl.CopyTexture(staging, veldridTexture);
            if (mip)
            {
                cl.GenerateMipmaps(veldridTexture);
            }
            cl.End();
            gd.SubmitCommands(cl);

            return(veldridTexture);
        }
Exemple #8
0
        /// <summary>
        /// Returns the number of texels in the texture that DO NOT match the fill value.
        /// </summary>
        private static int CountTexelsNotFilledAtDepth <TexelType>(GraphicsDevice device, Texture texture, TexelType fillValue, uint depth)
            where TexelType : unmanaged
        {
            ResourceFactory factory = device.ResourceFactory;

            // We need to create a staging texture and copy into it.
            TextureDescription description = new TextureDescription(texture.Width, texture.Height, depth: 1,
                                                                    texture.MipLevels, texture.ArrayLayers,
                                                                    texture.Format, TextureUsage.Staging,
                                                                    texture.Type, texture.SampleCount);

            Texture staging = factory.CreateTexture(ref description);

            using CommandList cl = factory.CreateCommandList();
            cl.Begin();

            cl.CopyTexture(texture,
                           srcX: 0, srcY: 0, srcZ: depth,
                           srcMipLevel: 0, srcBaseArrayLayer: 0,
                           staging,
                           dstX: 0, dstY: 0, dstZ: 0,
                           dstMipLevel: 0, dstBaseArrayLayer: 0,
                           staging.Width, staging.Height,
                           depth: 1, layerCount: 1);

            cl.End();
            device.SubmitCommands(cl);
            device.WaitForIdle();

            try
            {
                MappedResourceView <TexelType> mapped = device.Map <TexelType>(staging, MapMode.Read);

                int notFilledCount = 0;
                for (int y = 0; y < staging.Height; y++)
                {
                    for (int x = 0; x < staging.Width; x++)
                    {
                        TexelType actual = mapped[x, y];
                        if (!fillValue.Equals(actual))
                        {
                            notFilledCount++;
                        }
                    }
                }

                return(notFilledCount);
            }
            finally
            {
                device.Unmap(staging);
            }
        }
Exemple #9
0
        private unsafe Texture CreateTextureViaStaging(GraphicsDevice gd, ResourceFactory factory)
        {
            Texture staging = factory.CreateTexture(
                TextureDescription.Texture2D(Width, Height, MipLevels, 1, Format, TextureUsage.Staging));

            Texture ret = factory.CreateTexture(
                TextureDescription.Texture2D(Width, Height, MipLevels, 1, Format, TextureUsage.Sampled));

            CommandList cl = gd.ResourceFactory.CreateCommandList();

            cl.Begin();
            for (uint level = 0; level < MipLevels; level++)
            {
                Image <Rgba32> image = Images[level];
                if (!image.TryGetSinglePixelSpan(out Span <Rgba32> pixelSpan))
                {
                    throw new VeldridException("Unable to get image pixelspan.");
                }

                fixed(void *pin = &MemoryMarshal.GetReference(pixelSpan))
                {
                    MappedResource map      = gd.Map(staging, MapMode.Write, level);
                    uint           rowWidth = (uint)(image.Width * 4);

                    if (rowWidth == map.RowPitch)
                    {
                        Unsafe.CopyBlock(map.Data.ToPointer(), pin, (uint)(image.Width * image.Height * 4));
                    }
                    else
                    {
                        for (uint y = 0; y < image.Height; y++)
                        {
                            byte *dstStart = (byte *)map.Data.ToPointer() + y * map.RowPitch;
                            byte *srcStart = (byte *)pin + y * rowWidth;
                            Unsafe.CopyBlock(dstStart, srcStart, rowWidth);
                        }
                    }
                    gd.Unmap(staging, level);

                    cl.CopyTexture(
                        staging, 0, 0, 0, level, 0,
                        ret, 0, 0, 0, level, 0,
                        (uint)image.Width, (uint)image.Height, 1, 1);
                }
            }
            cl.End();

            gd.SubmitCommands(cl);
            staging.Dispose();
            cl.Dispose();

            return(ret);
        }
Exemple #10
0
        public void NonZeroMipLevel_ClearColor_Succeeds()
        {
            Texture testTex = RF.CreateTexture(
                TextureDescription.Texture2D(1024, 1024, 11, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget));

            Framebuffer[] framebuffers = new Framebuffer[11];
            for (uint level = 0; level < 11; level++)
            {
                framebuffers[level] = RF.CreateFramebuffer(
                    new FramebufferDescription(null, new[] { new FramebufferAttachmentDescription(testTex, 0, level) }));
            }

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            for (uint level = 0; level < 11; level++)
            {
                cl.SetFramebuffer(framebuffers[level]);
                cl.ClearColorTarget(0, new RgbaFloat(level, level, level, 1));
            }
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            Texture readback = RF.CreateTexture(
                TextureDescription.Texture2D(1024, 1024, 11, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Staging));

            cl.Begin();
            cl.CopyTexture(testTex, readback);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            uint mipWidth  = 1024;
            uint mipHeight = 1024;

            for (uint level = 0; level < 11; level++)
            {
                MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(readback, MapMode.Read, level);
                for (uint y = 0; y < mipHeight; y++)
                {
                    for (uint x = 0; x < mipWidth; x++)
                    {
                        Assert.Equal(new RgbaFloat(level, level, level, 1), readView[x, y]);
                    }
                }

                GD.Unmap(readback, level);
                mipWidth  = Math.Max(1, mipWidth / 2);
                mipHeight = Math.Max(1, mipHeight / 2);
            }
        }
Exemple #11
0
        public unsafe void Copy_Compressed_Texture(PixelFormat format, uint blockSizeInBytes, uint srcX, uint srcY, uint copyWidth, uint copyHeight)
        {
            if (!GD.GetPixelFormatSupport(format, TextureType.Texture2D, TextureUsage.Sampled))
            {
                return;
            }

            Texture copySrc = RF.CreateTexture(TextureDescription.Texture2D(
                                                   64, 64, 1, 1, format, TextureUsage.Staging));
            Texture copyDst = RF.CreateTexture(TextureDescription.Texture2D(
                                                   copyWidth, copyHeight, 1, 1, format, TextureUsage.Staging));

            const int numPixelsInBlockSide = 4;
            const int numPixelsInBlock     = 16;

            uint totalDataSize = copyWidth * copyHeight / numPixelsInBlock * blockSizeInBytes;

            byte[] data = new byte[totalDataSize];

            for (int i = 0; i < data.Length; i++)
            {
                data[i] = (byte)i;
            }

            fixed(byte *dataPtr = data)
            {
                GD.UpdateTexture(copySrc, (IntPtr)dataPtr, totalDataSize, srcX, srcY, 0, copyWidth, copyHeight, 1, 0, 0);
            }

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.CopyTexture(
                copySrc, srcX, srcY, 0, 0, 0,
                copyDst, 0, 0, 0, 0, 0,
                copyWidth, copyHeight, 1, 1);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            uint numBytesPerRow            = copyWidth / numPixelsInBlockSide * blockSizeInBytes;
            MappedResourceView <byte> view = GD.Map <byte>(copyDst, MapMode.Read);

            for (uint i = 0; i < data.Length; i++)
            {
                uint viewRow   = i / numBytesPerRow;
                uint viewIndex = (view.MappedResource.RowPitch * viewRow) + (i % numBytesPerRow);
                Assert.Equal(data[i], view[viewIndex]);
            }
            GD.Unmap(copyDst);
        }
Exemple #12
0
        public unsafe Texture CreateDeviceTexture(GraphicsDevice gd, ResourceFactory rf, TextureUsage usage)
        {
            if (gd == null)
            {
                throw new ArgumentNullException(nameof(gd));
            }
            if (rf == null)
            {
                throw new ArgumentNullException(nameof(rf));
            }

            using Texture staging = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format.ToVeldrid(), TextureUsage.Staging, Type));
            staging.Name          = "T_" + Name + "_Staging";

            ulong offset = 0;

            fixed(uint *texDataPtr = &_pixelData[0])
            {
                for (uint level = 0; level < MipLevels; level++)
                {
                    uint mipWidth        = GetDimension(Width, level);
                    uint mipHeight       = GetDimension(Height, level);
                    uint mipDepth        = GetDimension(Depth, level);
                    uint subresourceSize = mipWidth * mipHeight * mipDepth * FormatSize;

                    for (uint layer = 0; layer < ArrayLayers; layer++)
                    {
                        gd.UpdateTexture(
                            staging, (IntPtr)(texDataPtr + offset), subresourceSize,
                            0, 0, 0, mipWidth, mipHeight, mipDepth,
                            level, layer);
                        offset += subresourceSize;
                    }
                }
            }

            Texture texture = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format.ToVeldrid(), usage, Type));

            texture.Name = "T_" + Name;

            using (CommandList cl = rf.CreateCommandList())
            {
                cl.Begin();
                cl.CopyTexture(staging, texture);
                cl.End();
                gd.SubmitCommands(cl);
            }

            IsDirty = false;
            return(texture);
        }
Exemple #13
0
        private protected override void UpdateTextureCore(
            Texture texture,
            IntPtr source,
            uint sizeInBytes,
            uint x,
            uint y,
            uint z,
            uint width,
            uint height,
            uint depth,
            uint mipLevel,
            uint arrayLayer)
        {
            MTLTexture mtlTex = Util.AssertSubtype <Texture, MTLTexture>(texture);

            if (mtlTex.StagingBuffer.IsNull)
            {
                Texture stagingTex = ResourceFactory.CreateTexture(new TextureDescription(
                                                                       width, height, depth, 1, 1, texture.Format, TextureUsage.Staging, texture.Type));
                UpdateTexture(stagingTex, source, sizeInBytes, 0, 0, 0, width, height, depth, 0, 0);
                CommandList cl = ResourceFactory.CreateCommandList();
                cl.Begin();
                cl.CopyTexture(
                    stagingTex, 0, 0, 0, 0, 0,
                    texture, x, y, z, mipLevel, arrayLayer,
                    width, height, depth, 1);
                cl.End();
                SubmitCommands(cl);

                cl.Dispose();
                stagingTex.Dispose();
            }
            else
            {
                mtlTex.GetSubresourceLayout(mipLevel, arrayLayer, out uint dstRowPitch, out uint dstDepthPitch);
                ulong dstOffset     = Util.ComputeSubresourceOffset(mtlTex, mipLevel, arrayLayer);
                uint  srcRowPitch   = FormatHelpers.GetRowPitch(width, texture.Format);
                uint  srcDepthPitch = FormatHelpers.GetDepthPitch(srcRowPitch, height, texture.Format);
                Util.CopyTextureRegion(
                    source.ToPointer(),
                    0, 0, 0,
                    srcRowPitch, srcDepthPitch,
                    (byte *)mtlTex.StagingBuffer.contents() + dstOffset,
                    x, y, z,
                    dstRowPitch, dstDepthPitch,
                    width, height, depth,
                    texture.Format);
            }
        }
        private unsafe Texture CreateTextureViaStaging(GraphicsDevice gd, ResourceFactory factory)
        {
            Texture staging = factory.CreateTexture(
                new TextureDescription(Width, Height, 1, MipLevels, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging));

            Texture ret = factory.CreateTexture(
                new TextureDescription(Width, Height, 1, MipLevels, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Sampled));

            CommandList cl = gd.ResourceFactory.CreateCommandList();

            cl.Begin();
            for (uint level = 0; level < MipLevels; level++)
            {
                Image <Rgba32> image = Images[level];
                fixed(void *pin = &image.DangerousGetPinnableReferenceToPixelBuffer())
                {
                    MappedResource map      = gd.Map(staging, MapMode.Write, level);
                    uint           rowWidth = (uint)(image.Width * 4);

                    if (rowWidth == map.RowPitch)
                    {
                        Unsafe.CopyBlock(map.Data.ToPointer(), pin, (uint)(image.Width * image.Height * 4));
                    }
                    else
                    {
                        for (uint y = 0; y < image.Height; y++)
                        {
                            byte *dstStart = (byte *)map.Data.ToPointer() + y * map.RowPitch;
                            byte *srcStart = (byte *)pin + y * rowWidth;
                            Unsafe.CopyBlock(dstStart, srcStart, rowWidth);
                        }
                    }
                    gd.Unmap(staging, level);

                    cl.CopyTexture(
                        staging, 0, 0, 0, level, 0,
                        ret, 0, 0, 0, level, 0,
                        (uint)image.Width, (uint)image.Height, 1, 1);
                }
            }
            cl.End();

            gd.ExecuteCommands(cl);
            cl.Dispose();
            staging.Dispose();

            return(ret);
        }
Exemple #15
0
        public unsafe Texture CreateTexture(GraphicsDevice gd, ResourceFactory rf, TextureUsage usage, ImageBuffer image)
        {
            uint MipLevels   = 1;
            uint Width       = (uint)image.Width;
            uint Height      = (uint)image.Height;
            uint Depth       = 1;       // (uint)image.BitDepth;
            uint ArrayLayers = 1;
            var  Format      = PixelFormat.B8_G8_R8_A8_UNorm;

            Texture texture = rf.CreateTexture(new TextureDescription(
                                                   Width, Height, Depth, MipLevels, ArrayLayers, Format, usage, TextureType.Texture2D));

            Texture staging = rf.CreateTexture(new TextureDescription(
                                                   Width, Height, Depth, MipLevels, ArrayLayers, Format, TextureUsage.Staging, TextureType.Texture2D));

            ulong offset = 0;

            fixed(byte *texDataPtr = &image.GetBuffer()[0])
            {
                for (uint level = 0; level < MipLevels; level++)
                {
                    uint mipWidth        = GetDimension(Width, level);
                    uint mipHeight       = GetDimension(Height, level);
                    uint mipDepth        = GetDimension(Depth, level);
                    uint subresourceSize = mipWidth * mipHeight * mipDepth * GetFormatSize(Format);

                    for (uint layer = 0; layer < ArrayLayers; layer++)
                    {
                        gd.UpdateTexture(
                            staging, (IntPtr)(texDataPtr + offset), subresourceSize,
                            0, 0, 0, mipWidth, mipHeight, mipDepth,
                            level, layer);
                        offset += subresourceSize;
                    }
                }
            }

            CommandList cl = rf.CreateCommandList();

            cl.Begin();
            cl.CopyTexture(staging, texture);
            cl.End();
            gd.SubmitCommands(cl);

            return(texture);
        }
Exemple #16
0
        public unsafe void Update_NonStaging_3D()
        {
            Texture tex3D = RF.CreateTexture(TextureDescription.Texture3D(
                                                 16, 16, 16, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Sampled));

            RgbaByte[] data = new RgbaByte[16 * 16 * 16];
            for (int z = 0; z < 16; z++)
                for (int y = 0; y < 16; y++)
                {
                    for (int x = 0; x < 16; x++)
                    {
                        int index = (int)(z * tex3D.Width * tex3D.Height + y * tex3D.Height + x);
                        data[index] = new RgbaByte((byte)x, (byte)y, (byte)z, 1);
                    }
                }

            fixed(RgbaByte *dataPtr = data)
            {
                GD.UpdateTexture(tex3D, (IntPtr)dataPtr, (uint)(data.Length * Unsafe.SizeOf <RgbaByte>()),
                                 0, 0, 0,
                                 tex3D.Width, tex3D.Height, tex3D.Depth,
                                 0, 0);
            }

            Texture staging = RF.CreateTexture(TextureDescription.Texture3D(
                                                   16, 16, 16, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging));

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.CopyTexture(tex3D, staging);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            MappedResourceView <RgbaByte> view = GD.Map <RgbaByte>(staging, MapMode.Read);

            for (int z = 0; z < tex3D.Depth; z++)
                for (int y = 0; y < tex3D.Height; y++)
                {
                    for (int x = 0; x < tex3D.Width; x++)
                    {
                        Assert.Equal(new RgbaByte((byte)x, (byte)y, (byte)z, 1), view[x, y, z]);
                    }
                }
}
Exemple #17
0
        public void Copy_WithOffsets_2D(TextureUsage srcUsage, TextureUsage dstUsage)
        {
            Texture src = RF.CreateTexture(TextureDescription.Texture2D(
                                               100, 100, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, srcUsage));

            Texture dst = RF.CreateTexture(TextureDescription.Texture2D(
                                               100, 100, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, dstUsage));

            RgbaByte[] srcData = new RgbaByte[src.Height * src.Width];
            for (int y = 0; y < src.Height; y++)
            {
                for (int x = 0; x < src.Width; x++)
                {
                    srcData[y * src.Width + x] = new RgbaByte((byte)x, (byte)y, 0, 1);
                }
            }

            GD.UpdateTexture(src, srcData, 0, 0, 0, src.Width, src.Height, 1, 0, 0);

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.CopyTexture(
                src,
                50, 50, 0, 0, 0,
                dst,
                10, 10, 0, 0, 0,
                50, 50, 1, 1);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            Texture readback = GetReadback(dst);
            MappedResourceView <RgbaByte> readView = GD.Map <RgbaByte>(readback, MapMode.Read);

            for (int y = 10; y < 60; y++)
            {
                for (int x = 10; x < 60; x++)
                {
                    Assert.Equal(new RgbaByte((byte)(x + 40), (byte)(y + 40), 0, 1), readView[x, y]);
                }
            }
            GD.Unmap(readback);
        }
Exemple #18
0
        public void Copy_WitOffsets_2D()
        {
            Texture src = RF.CreateTexture(TextureDescription.Texture2D(
                                               100, 100, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging));

            Texture dst = RF.CreateTexture(TextureDescription.Texture2D(
                                               100, 100, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging));

            MappedResourceView <RgbaByte> writeView = GD.Map <RgbaByte>(src, MapMode.Write);

            for (int y = 0; y < src.Height; y++)
            {
                for (int x = 0; x < src.Width; x++)
                {
                    writeView[x, y] = new RgbaByte((byte)x, (byte)y, 0, 1);
                }
            }
            GD.Unmap(src);

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.CopyTexture(
                src,
                50, 50, 0, 0, 0,
                dst, 10, 10, 0, 0, 0,
                50, 50, 1, 1);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            MappedResourceView <RgbaByte> readView = GD.Map <RgbaByte>(dst, MapMode.Read);

            for (int y = 10; y < 60; y++)
            {
                for (int x = 10; x < 60; x++)
                {
                    Assert.Equal(new RgbaByte((byte)(x + 40), (byte)(y + 40), 0, 1), readView[x, y]);
                }
            }
            GD.Unmap(dst);
        }
Exemple #19
0
        public void Copy_DifferentMip_1DTo2D()
        {
            if (!GD.Features.Texture1D)
            {
                return;
            }

            Texture tex1D = RF.CreateTexture(
                TextureDescription.Texture1D(200, 2, 1, PixelFormat.R16_UNorm, TextureUsage.Staging));
            Texture tex2D = RF.CreateTexture(
                TextureDescription.Texture2D(100, 10, 1, 1, PixelFormat.R16_UNorm, TextureUsage.Staging));

            MappedResourceView <ushort> writeView = GD.Map <ushort>(tex1D, MapMode.Write, 1);

            Assert.Equal(tex2D.Width, (uint)writeView.Count);
            for (int i = 0; i < writeView.Count; i++)
            {
                writeView[i] = (ushort)(i * 2);
            }
            GD.Unmap(tex1D, 1);

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.CopyTexture(
                tex1D, 0, 0, 0, 1, 0,
                tex2D, 0, 5, 0, 0, 0,
                tex2D.Width, 1, 1, 1);
            cl.End();
            GD.SubmitCommands(cl);
            GD.DisposeWhenIdle(cl);
            GD.WaitForIdle();

            MappedResourceView <ushort> readView = GD.Map <ushort>(tex2D, MapMode.Read);

            for (int i = 0; i < tex2D.Width; i++)
            {
                Assert.Equal((ushort)(i * 2), readView[i, 5]);
            }
            GD.Unmap(tex2D);
        }
Exemple #20
0
        /// <inheritdoc />
        public unsafe int RegisterTexture(Span <Color> pixels, int width, int height)
        {
            var     factory = GraphicsDevice.ResourceFactory;
            Texture staging = factory.CreateTexture(
                TextureDescription.Texture2D((uint)width, (uint)height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging));

            Texture ret = factory.CreateTexture(
                TextureDescription.Texture2D((uint)width, (uint)height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Sampled));

            CommandList cl = factory.CreateCommandList();

            cl.Begin();

            MappedResource map = GraphicsDevice.Map(staging, MapMode.Write, 0);

            if (width == map.RowPitch / 4)
            {
                var dst = new Span <Color>(map.Data.ToPointer(), width * height);
                pixels.CopyTo(dst);
            }
            else
            {
                for (var y = 0; y < height; y++)
                {
                    var dst = new Span <Color>(IntPtr.Add(map.Data, y * (int)map.RowPitch).ToPointer(), width);
                    var src = pixels.Slice(y * width, width);
                    src.CopyTo(dst);
                }
            }

            GraphicsDevice.Unmap(staging);

            cl.CopyTexture(staging, ret);
            cl.End();

            GraphicsDevice.SubmitCommands(cl);
            GraphicsDevice.DisposeWhenIdle(staging);
            GraphicsDevice.DisposeWhenIdle(cl);

            return(Register(ret));
        }
        public unsafe Texture CreateDeviceTexture(GraphicsDevice gd, ResourceFactory rf, TextureUsage usage)
        {
            if (gd == null)
            {
                throw new ArgumentNullException(nameof(gd));
            }
            if (rf == null)
            {
                throw new ArgumentNullException(nameof(rf));
            }
            using Texture staging = rf.CreateTexture(new TextureDescription(
                                                         Width, Height, Depth, MipLevels,
                                                         ArrayLayers, Format.ToVeldrid(), TextureUsage.Staging, Type));

            staging.Name = Name + "_Staging";

            fixed(uint *texDataPtr = &TextureData[0])
            {
                uint subresourceSize = Width * Height * 4;

                gd.UpdateTexture(
                    staging, (IntPtr)texDataPtr, subresourceSize,
                    0, 0, 0, Width, Height, 1, 0, 0);
            }

            Texture texture = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format.ToVeldrid(), usage, Type));

            texture.Name = Name;
            using (CommandList cl = rf.CreateCommandList()) // TODO: Update texture without a dedicated command list to improve perf.
            {
                cl.Begin();
                cl.CopyTexture(staging, texture);
                cl.End();
                gd.SubmitCommands(cl);
            }

            IsDirty = false;
            return(texture);
        }
        public unsafe Texture CreateDeviceTexture(GraphicsDevice gd, ResourceFactory rf, TextureUsage usage)
        {
            Texture texture = rf.CreateTexture(new TextureDescription(
                                                   Width, Height, Depth, MipLevels, ArrayLayers, Format, usage, Type));

            Texture staging = rf.CreateTexture(new TextureDescription(
                                                   Width, Height, Depth, MipLevels, ArrayLayers, Format, TextureUsage.Staging, Type));

            ulong offset = 0;

            fixed(byte *texDataPtr = &TextureData[0])
            {
                for (uint level = 0; level < MipLevels; level++)
                {
                    uint mipWidth        = GetDimension(Width, level);
                    uint mipHeight       = GetDimension(Height, level);
                    uint mipDepth        = GetDimension(Depth, level);
                    uint subresourceSize = mipWidth * mipHeight * mipDepth * GetFormatSize(Format);

                    for (uint layer = 0; layer < ArrayLayers; layer++)
                    {
                        gd.UpdateTexture(
                            staging, (IntPtr)(texDataPtr + offset), subresourceSize,
                            0, 0, 0, mipWidth, mipHeight, mipDepth,
                            level, layer);
                        offset += subresourceSize;
                    }
                }
            }

            CommandList cl = rf.CreateCommandList();

            cl.Begin();
            cl.CopyTexture(staging, texture);
            cl.End();
            gd.SubmitCommands(cl);

            return(texture);
        }
Exemple #23
0
        public unsafe void Copy_BC3_Unorm()
        {
            Texture copySrc = RF.CreateTexture(TextureDescription.Texture2D(
                                                   64, 64, 1, 1, PixelFormat.BC3_UNorm, TextureUsage.Staging));
            Texture copyDst = RF.CreateTexture(TextureDescription.Texture2D(
                                                   64, 64, 1, 1, PixelFormat.BC3_UNorm, TextureUsage.Staging));

            uint totalDataSize = copySrc.Width * copySrc.Height;

            byte[] data = new byte[totalDataSize];

            for (int i = 0; i < data.Length; i++)
            {
                data[i] = (byte)i;
            }

            fixed(byte *dataPtr = data)
            {
                GD.UpdateTexture(copySrc, (IntPtr)dataPtr, totalDataSize, 0, 0, 0, copySrc.Width, copySrc.Height, 1, 0, 0);
            }

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.CopyTexture(
                copySrc, 0, 0, 0, 0, 0,
                copyDst, 0, 0, 0, 0, 0,
                copySrc.Width, copySrc.Height, 1, 1);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();
            MappedResourceView <byte> view = GD.Map <byte>(copyDst, MapMode.Read);

            for (int i = 0; i < data.Length; i++)
            {
                Assert.Equal(view[i], data[i]);
            }
        }
Exemple #24
0
        public static Icon Load(RenderContext renderContext, IconPathPattern pathPattern)
        {
            ContentManager  content = renderContext.Content;
            ResourceFactory rf      = renderContext.ResourceFactory;
            Texture?        texture = null;
            CommandList     cl      = renderContext.RentCommandList();

            cl.Begin();
            uint layer = 0;

            foreach (string path in pathPattern.EnumeratePaths())
            {
                Texture staging = content.LoadTexture(path, staging: true);
                texture ??= rf.CreateTexture(TextureDescription.Texture2D(
                                                 staging.Width, staging.Height,
                                                 mipLevels: 1, arrayLayers: pathPattern.IconCount,
                                                 staging.Format, TextureUsage.Sampled
                                                 ));
                cl.CopyTexture(
                    staging,
                    srcX: 0, srcY: 0, srcZ: 0,
                    srcMipLevel: 0, srcBaseArrayLayer: 0,
                    texture,
                    dstX: 0, dstY: 0, dstZ: 0,
                    dstMipLevel: 0, layer++,
                    texture.Width, texture.Height,
                    depth: 1, layerCount: 1
                    );
            }
            cl.End();
            renderContext.GraphicsDevice.SubmitCommands(cl);
            renderContext.ReturnCommandList(cl);

            Debug.Assert(texture is not null);
            return(new Icon(texture));
        }
Exemple #25
0
        public unsafe void Copy_Compressed_Array(bool separateLayerCopies)
        {
            PixelFormat format = PixelFormat.BC3_UNorm;

            if (!GD.GetPixelFormatSupport(format, TextureType.Texture2D, TextureUsage.Sampled))
            {
                return;
            }

            TextureDescription texDesc = TextureDescription.Texture2D(
                16, 16,
                1, 4,
                format,
                TextureUsage.Sampled);

            Texture copySrc = RF.CreateTexture(texDesc);

            texDesc.Usage = TextureUsage.Staging;
            Texture copyDst = RF.CreateTexture(texDesc);

            for (uint layer = 0; layer < copySrc.ArrayLayers; layer++)
            {
                int    byteCount = 16 * 16;
                byte[] data      = Enumerable.Range(0, byteCount).Select(i => (byte)(i + layer)).ToArray();
                GD.UpdateTexture(
                    copySrc,
                    data,
                    0, 0, 0,
                    16, 16, 1,
                    0, layer);
            }

            CommandList copyCL = RF.CreateCommandList();

            copyCL.Begin();
            if (separateLayerCopies)
            {
                for (uint layer = 0; layer < copySrc.ArrayLayers; layer++)
                {
                    copyCL.CopyTexture(copySrc, 0, 0, 0, 0, layer, copyDst, 0, 0, 0, 0, layer, 16, 16, 1, 1);
                }
            }
            else
            {
                copyCL.CopyTexture(copySrc, 0, 0, 0, 0, 0, copyDst, 0, 0, 0, 0, 0, 16, 16, 1, copySrc.ArrayLayers);
            }
            copyCL.End();
            Fence fence = RF.CreateFence(false);

            GD.SubmitCommands(copyCL, fence);
            GD.WaitForFence(fence);

            for (uint layer = 0; layer < copyDst.ArrayLayers; layer++)
            {
                MappedResource map     = GD.Map(copyDst, MapMode.Read, layer);
                byte *         basePtr = (byte *)map.Data;

                int  index   = 0;
                uint rowSize = 64;
                uint numRows = 4;
                for (uint row = 0; row < numRows; row++)
                {
                    byte *rowBase = basePtr + (row * map.RowPitch);
                    for (uint x = 0; x < rowSize; x++)
                    {
                        Assert.Equal((byte)(index + layer), rowBase[x]);
                        index += 1;
                    }
                }

                GD.Unmap(copyDst, layer);
            }
        }
Exemple #26
0
        public unsafe void Points_WithTexture_UpdateUnrelated(bool useTextureView)
        {
            // This is a regression test for the case where a user modifies an unrelated texture
            // at a time after a ResourceSet containing a texture has been bound. The OpenGL
            // backend was caching texture state improperly, resulting in wrong textures being sampled.

            Texture target = RF.CreateTexture(TextureDescription.Texture2D(
                                                  50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget));
            Texture staging = RF.CreateTexture(TextureDescription.Texture2D(
                                                   50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Staging));

            Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, target));

            DeviceBuffer orthoBuffer = RF.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer));
            Matrix4x4    orthoMatrix = Matrix4x4.CreateOrthographicOffCenter(
                0,
                framebuffer.Width,
                framebuffer.Height,
                0,
                -1,
                1);

            GD.UpdateBuffer(orthoBuffer, 0, ref orthoMatrix);

            Texture sampledTexture = RF.CreateTexture(
                TextureDescription.Texture2D(1, 1, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Sampled));

            RgbaFloat white = RgbaFloat.White;

            GD.UpdateTexture(sampledTexture, (IntPtr)(&white), (uint)Unsafe.SizeOf <RgbaFloat>(), 0, 0, 0, 1, 1, 1, 0, 0);

            Texture shouldntBeSampledTexture = RF.CreateTexture(
                TextureDescription.Texture2D(1, 1, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Sampled));

            ShaderSetDescription shaderSet = new ShaderSetDescription(
                new VertexLayoutDescription[]
            {
                new VertexLayoutDescription(
                    new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2))
            },
                TestShaders.LoadVertexFragment(RF, "TexturedPoints"));

            ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                new ResourceLayoutElementDescription("Ortho", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                                                                new ResourceLayoutElementDescription("Tex", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                                new ResourceLayoutElementDescription("Smp", ResourceKind.Sampler, ShaderStages.Fragment)));

            ResourceSet set;

            if (useTextureView)
            {
                TextureView view = RF.CreateTextureView(sampledTexture);
                set = RF.CreateResourceSet(new ResourceSetDescription(layout, orthoBuffer, view, GD.PointSampler));
            }
            else
            {
                set = RF.CreateResourceSet(new ResourceSetDescription(layout, orthoBuffer, sampledTexture, GD.PointSampler));
            }

            GraphicsPipelineDescription gpd = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                DepthStencilStateDescription.Disabled,
                RasterizerStateDescription.Default,
                PrimitiveTopology.PointList,
                shaderSet,
                layout,
                framebuffer.OutputDescription);

            Pipeline pipeline = RF.CreateGraphicsPipeline(ref gpd);

            Vector2[] vertices = new Vector2[]
            {
                new Vector2(0.5f, 0.5f),
                new Vector2(15.5f, 15.5f),
                new Vector2(25.5f, 26.5f),
                new Vector2(3.5f, 25.5f),
            };

            DeviceBuffer vb = RF.CreateBuffer(
                new BufferDescription((uint)(Unsafe.SizeOf <Vector2>() * vertices.Length), BufferUsage.VertexBuffer));

            GD.UpdateBuffer(vb, 0, vertices);

            CommandList cl = RF.CreateCommandList();

            for (int i = 0; i < 2; i++)
            {
                cl.Begin();
                cl.SetFramebuffer(framebuffer);
                cl.ClearColorTarget(0, RgbaFloat.Black);
                cl.SetPipeline(pipeline);
                cl.SetVertexBuffer(0, vb);
                cl.SetGraphicsResourceSet(0, set);

                // Modify an unrelated texture.
                // This must have no observable effect on the next draw call.
                RgbaFloat pink = RgbaFloat.Pink;
                GD.UpdateTexture(shouldntBeSampledTexture,
                                 (IntPtr)(&pink), (uint)Unsafe.SizeOf <RgbaFloat>(),
                                 0, 0, 0,
                                 1, 1, 1,
                                 0, 0);

                cl.Draw((uint)vertices.Length);
                cl.End();
                GD.SubmitCommands(cl);
                GD.WaitForIdle();
            }

            cl.Begin();
            cl.CopyTexture(target, staging);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(staging, MapMode.Read);

            foreach (Vector2 vertex in vertices)
            {
                uint x = (uint)vertex.X;
                uint y = (uint)vertex.Y;
                if (!GD.IsUvOriginTopLeft || GD.IsClipSpaceYInverted)
                {
                    y = framebuffer.Height - y - 1;
                }

                Assert.Equal(white, readView[x, y], RgbaFloatFuzzyComparer.Instance);
            }
            GD.Unmap(staging);
        }
        public Texture CreateDeviceTexture(GraphicsDevice gd, ResourceFactory rf, TextureUsage usage)
        {
            using var _ = PerfTracker.FrameEvent("6.1.2.1 Rebuild MultiTextures");
            if (IsMetadataDirty)
            {
                RebuildLayers();
            }

            var palette = PaletteManager.Palette.GetCompletePalette();

            using var staging = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format, TextureUsage.Staging, Type));
            staging.Name      = "T_" + Name + "_Staging";

            Span <uint> toBuffer = stackalloc uint[(int)(Width * Height)];

            foreach (var lsi in LogicalSubImages)
            {
                //if (!rebuildAll && !lsi.IsPaletteAnimated) // TODO: Requires caching a single Texture and then modifying it
                //    continue;

                for (int i = 0; i < lsi.Frames; i++)
                {
                    toBuffer.Fill(lsi.IsAlphaTested ? 0 : 0xff000000);
                    Rebuild(lsi, i, toBuffer, palette);

                    uint destinationLayer = (uint)LayerLookup[new LayerKey(lsi.Id, i)];

                    unsafe
                    {
                        fixed(uint *toBufferPtr = toBuffer)
                        {
                            gd.UpdateTexture(
                                staging, (IntPtr)toBufferPtr, Width * Height * sizeof(uint),
                                0, 0, 0,
                                Width, Height, 1,
                                0, destinationLayer);
                        }
                    }
                }
            }

            /* TODO: Mipmap
             *  for (uint level = 1; level < MipLevels; level++)
             *  {
             *  } //*/

            var texture = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format, usage, Type));

            texture.Name = "T_" + Name;

            using (CommandList cl = rf.CreateCommandList())
            {
                cl.Begin();
                cl.CopyTexture(staging, texture);
                cl.End();
                gd.SubmitCommands(cl);
            }

            IsDirty = false;
            return(texture);
        }
Exemple #28
0
        public void Points_WithFloat16Color()
        {
            Texture target = RF.CreateTexture(TextureDescription.Texture2D(
                                                  50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget));
            Texture staging = RF.CreateTexture(TextureDescription.Texture2D(
                                                   50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Staging));

            Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, target));

            DeviceBuffer infoBuffer  = RF.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer));
            DeviceBuffer orthoBuffer = RF.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer));
            Matrix4x4    orthoMatrix = Matrix4x4.CreateOrthographicOffCenter(
                0,
                framebuffer.Width,
                framebuffer.Height,
                0,
                -1,
                1);

            GD.UpdateBuffer(orthoBuffer, 0, ref orthoMatrix);

            ShaderSetDescription shaderSet = new ShaderSetDescription(
                new VertexLayoutDescription[]
            {
                new VertexLayoutDescription(
                    new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2),
                    new VertexElementDescription("Color_Half", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Half4))
            },
                TestShaders.LoadVertexFragment(RF, "F16VertexAttribs"));

            ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                                                                new ResourceLayoutElementDescription("OrthoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex)));

            ResourceSet set = RF.CreateResourceSet(new ResourceSetDescription(layout, infoBuffer, orthoBuffer));

            GraphicsPipelineDescription gpd = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                DepthStencilStateDescription.Disabled,
                RasterizerStateDescription.Default,
                PrimitiveTopology.PointList,
                shaderSet,
                layout,
                framebuffer.OutputDescription);

            Pipeline pipeline = RF.CreateGraphicsPipeline(ref gpd);

            uint colorNormalizationFactor = 2500;

            const ushort f16_375  = 0x5DDC; // 375.0
            const ushort f16_500  = 0x5FD0; // 500.0
            const ushort f16_625  = 0x60E2; // 625.0
            const ushort f16_875  = 0x62D6; // 875.0
            const ushort f16_1250 = 0x64E2; // 1250.0
            const ushort f16_1875 = 0x6753; // 1875.0

            VertexCPU_UShort[] vertices = new VertexCPU_UShort[]
            {
                new VertexCPU_UShort
                {
                    Position = new Vector2(0.5f, 0.5f),
                    R        = f16_625,
                    G        = f16_1250,
                    B        = f16_1875,
                },
                new VertexCPU_UShort
                {
                    Position = new Vector2(10.5f, 12.5f),
                    R        = f16_625,
                    G        = f16_1250,
                    B        = f16_1875,
                },
                new VertexCPU_UShort
                {
                    Position = new Vector2(25.5f, 35.5f),
                    R        = f16_1875,
                    G        = f16_1250,
                    B        = f16_625,
                },
                new VertexCPU_UShort
                {
                    Position = new Vector2(49.5f, 49.5f),
                    R        = f16_375,
                    G        = f16_500,
                    B        = f16_875,
                },
            };

            RgbaFloat[] expectedColors = new[]
            {
                new RgbaFloat(
                    625.0f / colorNormalizationFactor,
                    1250.0f / colorNormalizationFactor,
                    1875.0f / colorNormalizationFactor,
                    1),
                new RgbaFloat(
                    625.0f / colorNormalizationFactor,
                    1250.0f / colorNormalizationFactor,
                    1875.0f / colorNormalizationFactor,
                    1),
                new RgbaFloat(
                    1875.0f / colorNormalizationFactor,
                    1250.0f / colorNormalizationFactor,
                    625.0f / colorNormalizationFactor,
                    1),
                new RgbaFloat(
                    375.0f / colorNormalizationFactor,
                    500.0f / colorNormalizationFactor,
                    875.0f / colorNormalizationFactor,
                    1),
            };

            DeviceBuffer vb = RF.CreateBuffer(
                new BufferDescription((uint)(Unsafe.SizeOf <UIntVertexAttribsVertex>() * vertices.Length), BufferUsage.VertexBuffer));

            GD.UpdateBuffer(vb, 0, vertices);
            GD.UpdateBuffer(infoBuffer, 0, new UIntVertexAttribsInfo {
                ColorNormalizationFactor = colorNormalizationFactor
            });

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.SetFramebuffer(framebuffer);
            cl.SetFullViewports();
            cl.SetFullScissorRects();
            cl.ClearColorTarget(0, RgbaFloat.Black);
            cl.SetPipeline(pipeline);
            cl.SetVertexBuffer(0, vb);
            cl.SetGraphicsResourceSet(0, set);
            cl.Draw((uint)vertices.Length);
            cl.CopyTexture(target, staging);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(staging, MapMode.Read);

            for (int i = 0; i < vertices.Length; i++)
            {
                VertexCPU_UShort vertex = vertices[i];
                uint             x      = (uint)vertex.Position.X;
                uint             y      = (uint)vertex.Position.Y;
                if (!GD.IsUvOriginTopLeft || GD.IsClipSpaceYInverted)
                {
                    y = framebuffer.Height - y - 1;
                }

                RgbaFloat expectedColor = expectedColors[i];
                Assert.Equal(expectedColor, readView[x, y], RgbaFloatFuzzyComparer.Instance);
            }
            GD.Unmap(staging);
        }
Exemple #29
0
        public static unsafe Texture LoadTexture(
            GraphicsDevice gd,
            ResourceFactory factory,
            Stream assetStream,
            PixelFormat format)
        {
            KtxFile ktxTex2D = Load(assetStream, false);

            uint width  = ktxTex2D.Header.PixelWidth;
            uint height = ktxTex2D.Header.PixelHeight;

            if (height == 0)
            {
                height = width;
            }

            uint arrayLayers = Math.Max(1, ktxTex2D.Header.NumberOfArrayElements);
            uint mipLevels   = Math.Max(1, ktxTex2D.Header.NumberOfMipmapLevels);

            Texture ret = factory.CreateTexture(TextureDescription.Texture2D(
                                                    width, height, mipLevels, arrayLayers,
                                                    format, TextureUsage.Sampled));

            Texture stagingTex = factory.CreateTexture(TextureDescription.Texture2D(
                                                           width, height, mipLevels, arrayLayers,
                                                           format, TextureUsage.Staging));

            // Copy texture data into staging buffer
            for (uint level = 0; level < mipLevels; level++)
            {
                KtxMipmapLevel mipmap = ktxTex2D.Mipmaps[level];
                for (uint layer = 0; layer < arrayLayers; layer++)
                {
                    KtxArrayElement ktxLayer = mipmap.ArrayElements[layer];
                    Debug.Assert(ktxLayer.Faces.Length == 1);
                    byte[] pixelData = ktxLayer.Faces[0].Data;
                    fixed(byte *pixelDataPtr = &pixelData[0])
                    {
                        gd.UpdateTexture(stagingTex, (IntPtr)pixelDataPtr, (uint)pixelData.Length,
                                         0, 0, 0, mipmap.Width, mipmap.Height, 1, level, layer);
                    }
                }
            }

            CommandList copyCL = factory.CreateCommandList();

            copyCL.Begin();
            for (uint level = 0; level < mipLevels; level++)
            {
                KtxMipmapLevel mipLevel = ktxTex2D.Mipmaps[level];
                for (uint layer = 0; layer < arrayLayers; layer++)
                {
                    copyCL.CopyTexture(
                        stagingTex, 0, 0, 0, level, layer,
                        ret, 0, 0, 0, level, layer,
                        mipLevel.Width, mipLevel.Height, mipLevel.Depth,
                        1);
                }
            }
            copyCL.End();
            gd.SubmitCommands(copyCL);

            gd.DisposeWhenIdle(copyCL);
            gd.DisposeWhenIdle(stagingTex);

            return(ret);
        }
Exemple #30
0
        public void Points_WithUShortColor()
        {
            Texture target = RF.CreateTexture(TextureDescription.Texture2D(
                                                  50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget));
            Texture staging = RF.CreateTexture(TextureDescription.Texture2D(
                                                   50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Staging));

            Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, target));

            DeviceBuffer infoBuffer  = RF.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer));
            DeviceBuffer orthoBuffer = RF.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer));
            Matrix4x4    orthoMatrix = Matrix4x4.CreateOrthographicOffCenter(
                0,
                framebuffer.Width,
                framebuffer.Height,
                0,
                -1,
                1);

            GD.UpdateBuffer(orthoBuffer, 0, ref orthoMatrix);

            ShaderSetDescription shaderSet = new ShaderSetDescription(
                new VertexLayoutDescription[]
            {
                new VertexLayoutDescription(
                    new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2),
                    new VertexElementDescription("Color_UInt", VertexElementSemantic.Color, VertexElementFormat.UShort4))
            },
                new Shader[]
            {
                TestShaders.Load(RF, "U16VertexAttribs", ShaderStages.Vertex, "VS"),
                TestShaders.Load(RF, "U16VertexAttribs", ShaderStages.Fragment, "FS")
            });

            ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex),
                                                                new ResourceLayoutElementDescription("Ortho", ResourceKind.UniformBuffer, ShaderStages.Vertex)));

            ResourceSet set = RF.CreateResourceSet(new ResourceSetDescription(layout, infoBuffer, orthoBuffer));

            GraphicsPipelineDescription gpd = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                DepthStencilStateDescription.Disabled,
                RasterizerStateDescription.Default,
                PrimitiveTopology.PointList,
                shaderSet,
                layout,
                framebuffer.OutputDescription);

            Pipeline pipeline = RF.CreateGraphicsPipeline(ref gpd);

            uint colorNormalizationFactor = 2500;

            VertexCPU_UShort[] vertices = new VertexCPU_UShort[]
            {
                new VertexCPU_UShort
                {
                    Position = new Vector2(0.5f, 0.5f),
                    R        = (ushort)(0.25f * colorNormalizationFactor),
                    G        = (ushort)(0.5f * colorNormalizationFactor),
                    B        = (ushort)(0.75f * colorNormalizationFactor),
                },
                new VertexCPU_UShort
                {
                    Position = new Vector2(10.5f, 12.5f),
                    R        = (ushort)(0.25f * colorNormalizationFactor),
                    G        = (ushort)(0.5f * colorNormalizationFactor),
                    B        = (ushort)(0.75f * colorNormalizationFactor),
                },
                new VertexCPU_UShort
                {
                    Position = new Vector2(25.5f, 35.5f),
                    R        = (ushort)(0.75f * colorNormalizationFactor),
                    G        = (ushort)(0.5f * colorNormalizationFactor),
                    B        = (ushort)(0.25f * colorNormalizationFactor),
                },
                new VertexCPU_UShort
                {
                    Position = new Vector2(49.5f, 49.5f),
                    R        = (ushort)(0.15f * colorNormalizationFactor),
                    G        = (ushort)(0.2f * colorNormalizationFactor),
                    B        = (ushort)(0.35f * colorNormalizationFactor),
                },
            };

            DeviceBuffer vb = RF.CreateBuffer(
                new BufferDescription((uint)(Unsafe.SizeOf <UIntVertexAttribs.Vertex>() * vertices.Length), BufferUsage.VertexBuffer));

            GD.UpdateBuffer(vb, 0, vertices);
            GD.UpdateBuffer(infoBuffer, 0, new UIntVertexAttribs.Info {
                ColorNormalizationFactor = colorNormalizationFactor
            });

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.SetFramebuffer(framebuffer);
            cl.SetFullViewports();
            cl.SetFullScissorRects();
            cl.ClearColorTarget(0, RgbaFloat.Black);
            cl.SetPipeline(pipeline);
            cl.SetVertexBuffer(0, vb);
            cl.SetGraphicsResourceSet(0, set);
            cl.Draw((uint)vertices.Length);
            cl.SetFramebuffer(GD.SwapchainFramebuffer);
            cl.ClearColorTarget(0, RgbaFloat.Red);
            cl.CopyTexture(target, staging);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(staging, MapMode.Read);

            foreach (VertexCPU_UShort vertex in vertices)
            {
                uint x = (uint)vertex.Position.X;
                uint y = (uint)vertex.Position.Y;
                if (GD.BackendType == GraphicsBackend.OpenGL)
                {
                    y = framebuffer.Height - y - 1;
                }

                RgbaFloat expectedColor = new RgbaFloat(
                    vertex.R / (float)colorNormalizationFactor,
                    vertex.G / (float)colorNormalizationFactor,
                    vertex.B / (float)colorNormalizationFactor,
                    1);
                Assert.Equal(expectedColor, readView[x, y], RgbaFloatFuzzyComparer.Instance);
            }
            GD.Unmap(staging);
        }