コード例 #1
0
        public unsafe void MapWrite_ThenMapRead_3D()
        {
            Texture tex3D = RF.CreateTexture(TextureDescription.Texture3D(
                                                 10, 10, 10, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging));

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

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

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

            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), readView[x, y, z]);
                    }
                }
            }
            GD.Unmap(tex3D);
        }
コード例 #2
0
        public unsafe void Map_NonZeroMip_3D()
        {
            Texture tex3D = RF.CreateTexture(TextureDescription.Texture3D(
                                                 40, 40, 40, 3, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging));

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

            for (int z = 0; z < 10; z++)
            {
                for (int y = 0; y < 10; y++)
                {
                    for (int x = 0; x < 10; x++)
                    {
                        writeView[x, y, z] = new RgbaByte((byte)x, (byte)y, (byte)z, 1);
                    }
                }
            }
            GD.Unmap(tex3D, 2);

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

            for (int z = 0; z < 10; z++)
            {
                for (int y = 0; y < 10; y++)
                {
                    for (int x = 0; x < 10; x++)
                    {
                        Assert.Equal(new RgbaByte((byte)x, (byte)y, (byte)z, 1), readView[x, y, z]);
                    }
                }
            }
            GD.Unmap(tex3D, 2);
        }
コード例 #3
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]);
                    }
                }
}
コード例 #4
0
        public unsafe void Update_ThenMapRead_3D()
        {
            Texture tex3D = RF.CreateTexture(TextureDescription.Texture3D(
                                                 10, 10, 10, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging));

            RgbaByte[] data = new RgbaByte[tex3D.Width * tex3D.Height * tex3D.Depth];
            for (int z = 0; z < tex3D.Depth; z++)
            {
                for (int y = 0; y < tex3D.Height; y++)
                {
                    for (int x = 0; x < tex3D.Width; 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);
                }

                MappedResourceView <RgbaByte> view = GD.Map <RgbaByte>(tex3D, MapMode.Read, 0);
                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]);
                        }
                    }
                }
                GD.Unmap(tex3D);
        }
コード例 #5
0
        public void ComputeShader3dTexture()
        {
            // Just a dumb compute shader that fills a 3D texture with the same value from a uniform multiplied by the depth.
            string shaderText = @"
#version 450
layout(set = 0, binding = 0, rgba32f) uniform image3D TextureToFill;
layout(set = 0, binding = 1) uniform FillValueBuffer
{
    float FillValue;
    float Padding1;
    float Padding2;
    float Padding3;
};
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main()
{
    ivec3 textureCoordinate = ivec3(gl_GlobalInvocationID.xyz);
    float dataToStore = FillValue * (textureCoordinate.z + 1);

    imageStore(TextureToFill, textureCoordinate, vec4(dataToStore));
}
";

            const float FillValue         = 42.42f;
            const uint  OutputTextureSize = 32;

            using Shader computeShader = RF.CreateFromSpirv(new ShaderDescription(
                                                                ShaderStages.Compute,
                                                                Encoding.ASCII.GetBytes(shaderText),
                                                                "main"));

            using ResourceLayout computeLayout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                             new ResourceLayoutElementDescription("TextureToFill", ResourceKind.TextureReadWrite, ShaderStages.Compute),
                                                                             new ResourceLayoutElementDescription("FillValueBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute)));

            using Pipeline computePipeline = RF.CreateComputePipeline(new ComputePipelineDescription(
                                                                          computeShader,
                                                                          computeLayout,
                                                                          16, 16, 1));

            using DeviceBuffer fillValueBuffer = RF.CreateBuffer(new BufferDescription((uint)Marshal.SizeOf <FillValueStruct>(), BufferUsage.UniformBuffer));

            // Create our output texture.
            using Texture computeTargetTexture = RF.CreateTexture(TextureDescription.Texture3D(
                                                                      OutputTextureSize,
                                                                      OutputTextureSize,
                                                                      OutputTextureSize,
                                                                      1,
                                                                      PixelFormat.R32_G32_B32_A32_Float,
                                                                      TextureUsage.Sampled | TextureUsage.Storage));

            using TextureView computeTargetTextureView = RF.CreateTextureView(computeTargetTexture);

            using ResourceSet computeResourceSet = RF.CreateResourceSet(new ResourceSetDescription(
                                                                            computeLayout,
                                                                            computeTargetTextureView,
                                                                            fillValueBuffer));

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

            cl.UpdateBuffer(fillValueBuffer, 0, new FillValueStruct(FillValue));

            // Use the compute shader to fill the texture.
            cl.SetPipeline(computePipeline);
            cl.SetComputeResourceSet(0, computeResourceSet);
            const uint GroupDivisorXY = 16;

            cl.Dispatch(OutputTextureSize / GroupDivisorXY, OutputTextureSize / GroupDivisorXY, OutputTextureSize);

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

            // Read back from our texture and make sure it has been properly filled.
            for (uint depth = 0; depth < computeTargetTexture.Depth; depth++)
            {
                RgbaFloat expectedFillValue = new RgbaFloat(new System.Numerics.Vector4(FillValue * (depth + 1)));
                int       notFilledCount    = CountTexelsNotFilledAtDepth(GD, computeTargetTexture, expectedFillValue, depth);

                if (notFilledCount == 0)
                {
                    // Expected behavior:
                    Console.WriteLine($"All texels were properly set at depth {depth}");
                }
                else
                {
                    // Unexpected behavior:
                    uint totalTexels = computeTargetTexture.Width * computeTargetTexture.Height;
                    throw new Exception($"{notFilledCount} of {totalTexels} texels were not properly set at depth {depth}");
                }
            }
        }