Exemplo n.º 1
0
        protected void CopyTo(BaseResource dest, SubresourceBox srcBox, uint srcSubresourceIndex, uint dstSubresourceIndex,
                              uint dstX, uint dstY, uint dstZ)
        {
            Assure.NotNull(dest);
            Assure.False(this == dest && srcSubresourceIndex == dstSubresourceIndex, "Can not copy to/from same subresource.");
            dest.ThrowIfCannotBeCopyDestination();

            lock (InstanceMutationLock) {
                if (IsDisposed)
                {
                    Logger.Warn("Attempted copy manipulation from disposed resource of type: " + GetType().Name);
                    return;
                }
                lock (dest.InstanceMutationLock) {
                    if (IsDisposed)
                    {
                        Logger.Warn("Attempted copy manipulation to disposed resource of type: " + GetType().Name);
                        return;
                    }
                    InteropUtils.CallNative(
                        NativeMethods.ResourceFactory_CopySubresourceRegion,
                        RenderingModule.DeviceContext,
                        ResourceHandle,
                        srcSubresourceIndex,
                        (IntPtr)(&srcBox),
                        dest.ResourceHandle,
                        dstSubresourceIndex,
                        dstX,
                        dstY,
                        dstZ
                        ).ThrowOnFailure();
                }
            }
        }
Exemplo n.º 2
0
        public void TestWrite()
        {
            LosgapSystem.InvokeOnMaster(() => {
                // Define variables and constants
                const uint WIDTH_TX  = 100U;
                const uint HEIGHT_TX = 100U;

                const uint WRITE_OFFSET_U = 30U;
                const uint WRITE_OFFSET_V = 30U;

                SubresourceBox writeTarget = new SubresourceBox(
                    WRITE_OFFSET_U, WIDTH_TX,
                    WRITE_OFFSET_V, HEIGHT_TX
                    );

                Texture2D <TexelFormat.RGBA8Int> srcTex = TextureFactory.NewTexture2D <TexelFormat.RGBA8Int>()
                                                          .WithUsage(ResourceUsage.Write)
                                                          .WithMultisampling(true)
                                                          .WithWidth(WIDTH_TX)
                                                          .WithHeight(HEIGHT_TX);

                // Set up context


                // Execute
                srcTex.Write(
                    Enumerable.Range(0, (int)writeTarget.Volume)
                    .Select(i => new TexelFormat.RGBA8Int {
                    R = (sbyte)i, G = (sbyte)(i * 2), B = (sbyte)(i * 3), A = (sbyte)(i * 4)
                })
                    .ToArray(),
                    writeTarget
                    );

                Texture2D <TexelFormat.RGBA8Int> dstTex = srcTex.Clone()
                                                          .WithUsage(ResourceUsage.StagingRead)
                                                          .WithPermittedBindings(GPUBindings.None);

                srcTex.CopyTo(dstTex);

                // Assert outcome
                TexelArray2D <TexelFormat.RGBA8Int> copiedData = dstTex.Read(0U);
                for (uint v = WRITE_OFFSET_V, value = 0U; v < HEIGHT_TX; ++v)
                {
                    for (uint u = WRITE_OFFSET_U; u < WIDTH_TX; ++u, ++value)
                    {
                        Assert.AreEqual((sbyte)value, copiedData[(int)u, (int)v].R);
                        Assert.AreEqual((sbyte)(value * 2U), copiedData[(int)u, (int)v].G);
                        Assert.AreEqual((sbyte)(value * 3U), copiedData[(int)u, (int)v].B);
                        Assert.AreEqual((sbyte)(value * 4U), copiedData[(int)u, (int)v].A);
                    }
                }

                srcTex.Dispose();
                dstTex.Dispose();
            });
        }
Exemplo n.º 3
0
        public void CopyTo(Texture2D <TTexel> dest, SubresourceBox srcRegion, uint srcMipIndex = 0U, uint dstMipIndex = 0U,
                           uint destWriteOffsetX = 0U, uint destWriteOffsetY = 0U)
        {
            Assure.LessThan(
                srcMipIndex, NumMips,
                "Can not copy from mip level " + srcMipIndex + ": Only " + NumMips + " present in source texture."
                );
            Assure.LessThan(
                dstMipIndex, dest.NumMips,
                "Can not copy to mip level " + dstMipIndex + ": Only " + dest.NumMips + " present in destination texture."
                );
            Assure.LessThan(
                srcRegion.Left,
                MipWidth(srcMipIndex),
                "Buffer overflow: Please ensure you are not attempting to copy from past the end of the source texture."
                );
            Assure.LessThanOrEqualTo(
                srcRegion.Right,
                MipWidth(srcMipIndex),
                "Buffer overflow: Please ensure you are not attempting to copy from past the end of the source texture."
                );
            Assure.LessThan(
                srcRegion.Top,
                MipHeight(srcMipIndex),
                "Buffer overflow: Please ensure you are not attempting to copy from past the end of the source texture."
                );
            Assure.LessThanOrEqualTo(
                srcRegion.Bottom,
                MipHeight(srcMipIndex),
                "Buffer overflow: Please ensure you are not attempting to copy from past the end of the source texture."
                );
            Assure.LessThanOrEqualTo(
                srcRegion.Width + destWriteOffsetX,
                dest.MipWidth(dstMipIndex),
                "Buffer overflow: Please ensure you are not attempting to copy to past the end of the destination texture."
                );
            Assure.LessThanOrEqualTo(
                srcRegion.Height + destWriteOffsetY,
                dest.MipHeight(dstMipIndex),
                "Buffer overflow: Please ensure you are not attempting to copy to past the end of the destination texture."
                );

            base.CopyTo(
                dest,
                srcRegion,
                GetSubresourceIndex(srcMipIndex),
                dest.GetSubresourceIndex(dstMipIndex),
                destWriteOffsetX,
                destWriteOffsetY,
                0U
                );
        }
 private void Mutate_UpdateSubresourceRegion(IntPtr data, SubresourceBox updateBox)
 {
     lock (InstanceMutationLock) {
         if (IsDisposed)
         {
             Logger.Warn("Attempted write manipulation on disposed resource of type: " + GetType().Name);
             return;
         }
         InteropUtils.CallNative(
             NativeMethods.ResourceFactory_UpdateSubresourceRegion,
             RenderingModule.DeviceContext,
             ResourceHandle,
             0U,
             (IntPtr)(&updateBox),
             data,
             (uint)Size,
             (uint)Size
             ).ThrowOnFailure();
     }
 }
Exemplo n.º 5
0
        private void Mutate_MapWrite(GCHandle pinnedDataHandle, SubresourceBox dataDesc, uint mipIndex)
        {
            LosgapSystem.InvokeOnMasterAsync(() => {
                IntPtr dstDataPtr;
                uint outRowStrideBytes, outSliceStrideBytes;
                InteropUtils.CallNative(
                    NativeMethods.ResourceFactory_MapSubresource,
                    RenderingModule.DeviceContext,
                    ResourceHandle,
                    GetSubresourceIndex(mipIndex),
                    ResourceMapping.Write,
                    (IntPtr)(&dstDataPtr),
                    (IntPtr)(&outRowStrideBytes),
                    (IntPtr)(&outSliceStrideBytes)
                    ).ThrowOnFailure();

                try {
                    IntPtr srcDataPtr = pinnedDataHandle.AddrOfPinnedObject();
                    for (uint srcSlice = 0U, dstSliceStart = outSliceStrideBytes * dataDesc.Front;
                         srcSlice < dataDesc.Depth;
                         ++srcSlice, dstSliceStart += outSliceStrideBytes)
                    {
                        for (uint srcRow = 0U, dstRowStart = outRowStrideBytes * dataDesc.Top;
                             srcRow < dataDesc.Height;
                             ++srcRow, dstRowStart += outRowStrideBytes)
                        {
                            UnsafeUtils.MemCopy(srcDataPtr + (int)((dataDesc.Width * srcRow + dataDesc.Height * srcSlice) * TexelSizeBytes),
                                                dstDataPtr + (int)(dataDesc.Left + dstRowStart + dstSliceStart), dataDesc.Width * TexelSizeBytes);
                        }
                    }
                }
                finally {
                    InteropUtils.CallNative(
                        NativeMethods.ResourceFactory_UnmapSubresource,
                        RenderingModule.DeviceContext,
                        ResourceHandle,
                        GetSubresourceIndex(mipIndex)
                        ).ThrowOnFailure();
                }
            });
        }
        public void TestDerivedProperties()
        {
            // Define variables and constants
            SubresourceBox box1 = new SubresourceBox(10, 30);
            SubresourceBox box2 = new SubresourceBox(10, 30, 20, 50);
            SubresourceBox box3 = new SubresourceBox(10, 30, 20, 50, 60, 100);

            // Set up context


            // Execute


            // Assert outcome
            Assert.AreEqual(20U, box1.Width);
            Assert.AreEqual(20U, box2.Width);
            Assert.AreEqual(20U, box3.Width);
            Assert.AreEqual(30U, box2.Height);
            Assert.AreEqual(30U, box3.Height);
            Assert.AreEqual(40U, box3.Depth);
            Assert.AreEqual(20U, box1.Volume);
            Assert.AreEqual(600U, box2.Volume);
            Assert.AreEqual(24000U, box3.Volume);
        }
Exemplo n.º 7
0
        public void TestCopyTo()
        {
            LosgapSystem.InvokeOnMaster(() => {
                // Define variables and constants
                const uint WIDTH_TX  = 256U;
                const uint HEIGHT_TX = 32U;
                const uint DEPTH_TX  = 32U;

                const uint NUM_TEXELS_TO_COPY_PER_ROW = 25U;
                const uint FIRST_TEXEL_TO_COPY_IN_ROW = 25U;
                const uint NUM_ROWS_TO_COPY_PER_SLICE = 5U;
                const uint FIRST_ROW_TO_COPY_IN_SLICE = 1U;
                const uint NUM_SLICES_TO_COPY         = 10U;
                const uint FIRST_SLICE_TO_COPY        = 4U;
                const uint SRC_MIP_INDEX      = 1U;
                const uint DST_MIP_INDEX      = 1U;
                const uint DST_WRITE_OFFSET_X = 15U;
                const uint DST_WRITE_OFFSET_Y = 2U;
                const uint DST_WRITE_OFFSET_Z = 0U;

                const float DATA_VALUE_ADDITION_W = (float)(HEIGHT_TX >> 1) * (float)(WIDTH_TX >> 1);
                const float DATA_VALUE_ADDITION_V = (float)(WIDTH_TX >> 1);
                const float DATA_VALUE_START_R    =
                    WIDTH_TX * HEIGHT_TX * DEPTH_TX
                    + FIRST_TEXEL_TO_COPY_IN_ROW
                    + DATA_VALUE_ADDITION_V * FIRST_ROW_TO_COPY_IN_SLICE
                    + DATA_VALUE_ADDITION_W * FIRST_SLICE_TO_COPY;

                TexelFormat.RGBA32Float[] initialData = Enumerable.Range(0, (int)TextureUtils.GetSizeTexels(true, WIDTH_TX, HEIGHT_TX, DEPTH_TX))
                                                        .Select(i => new TexelFormat.RGBA32Float {
                    R = (float)i, G = (float)i * 2f, B = (float)i * 4f, A = (float)i * 8f
                })
                                                        .ToArray();

                Texture3D <TexelFormat.RGBA32Float> srcTex = TextureFactory.NewTexture3D <TexelFormat.RGBA32Float>()
                                                             .WithDynamicDetail(false)
                                                             .WithInitialData(initialData)
                                                             .WithMipAllocation(true)
                                                             .WithMipGenerationTarget(false)
                                                             .WithPermittedBindings(GPUBindings.ReadableShaderResource)
                                                             .WithUsage(ResourceUsage.Immutable)
                                                             .WithWidth(WIDTH_TX)
                                                             .WithHeight(HEIGHT_TX)
                                                             .WithDepth(DEPTH_TX);

                // Set up context

                // Execute
                Texture3D <TexelFormat.RGBA32Float> dstTex = srcTex.Clone()
                                                             .WithUsage(ResourceUsage.StagingRead)
                                                             .WithPermittedBindings(GPUBindings.None);
                SubresourceBox targetBox = new SubresourceBox(
                    FIRST_TEXEL_TO_COPY_IN_ROW, FIRST_TEXEL_TO_COPY_IN_ROW + NUM_TEXELS_TO_COPY_PER_ROW,
                    FIRST_ROW_TO_COPY_IN_SLICE, FIRST_ROW_TO_COPY_IN_SLICE + NUM_ROWS_TO_COPY_PER_SLICE,
                    FIRST_SLICE_TO_COPY, FIRST_SLICE_TO_COPY + NUM_SLICES_TO_COPY
                    );
                srcTex.CopyTo(
                    dstTex,
                    targetBox,
                    SRC_MIP_INDEX,
                    DST_MIP_INDEX,
                    DST_WRITE_OFFSET_X,
                    DST_WRITE_OFFSET_Y,
                    DST_WRITE_OFFSET_Z
                    );

                // Assert outcome
                TexelArray3D <TexelFormat.RGBA32Float> copiedData = dstTex.Read(DST_MIP_INDEX);
                for (int w = 0; w < NUM_SLICES_TO_COPY; ++w)
                {
                    for (int v = 0; v < NUM_ROWS_TO_COPY_PER_SLICE; ++v)
                    {
                        for (int u = 0; u < NUM_TEXELS_TO_COPY_PER_ROW; ++u)
                        {
                            var thisTexel = copiedData[u + (int)DST_WRITE_OFFSET_X, v + (int)DST_WRITE_OFFSET_Y, w + (int)DST_WRITE_OFFSET_Z];
                            Assert.AreEqual((float)(DATA_VALUE_START_R + u + v * DATA_VALUE_ADDITION_V + w * DATA_VALUE_ADDITION_W), thisTexel.R);
                            Assert.AreEqual((float)(DATA_VALUE_START_R + u + v * DATA_VALUE_ADDITION_V + w * DATA_VALUE_ADDITION_W) * 2f, thisTexel.G);
                            Assert.AreEqual((float)(DATA_VALUE_START_R + u + v * DATA_VALUE_ADDITION_V + w * DATA_VALUE_ADDITION_W) * 4f, thisTexel.B);
                            Assert.AreEqual((float)(DATA_VALUE_START_R + u + v * DATA_VALUE_ADDITION_V + w * DATA_VALUE_ADDITION_W) * 8f, thisTexel.A);
                        }
                    }
                }

                srcTex.Dispose();
                dstTex.Dispose();
            });
        }
Exemplo n.º 8
0
        /// <summary>
        /// Performs a <see cref="ResourceUsage.Write"/> on this texture, copying the supplied data to the resource.
        /// </summary>
        /// <param name="data">The data to write.
        /// <see cref="ArraySlice{T}.Length">Length</see> vertices will be copied from the given
        /// array slice. The copy will start from the specified <see cref="ArraySlice{T}.Offset">Offset</see> in the
        /// contained array.
        /// </param>
        /// <param name="writeOffsetX">The first texel in this texture to start copying the data to.</param>
        /// <param name="mipIndex">The mip level to write to. Only one mip level may be written to at a time. If this texture
        /// is not mipmapped, you must supply a value of <c>0U</c>.</param>
        /// <exception cref="ResourceOperationUnavailableException">Thrown if <see cref="BaseResource.CanDiscardWrite"/> is
        /// <c>false</c>.</exception>
        /// <exception cref="AssuranceFailedException">(Debug only) Thrown if the combination of supplied parameters would
        /// result in writing past the end of the texture in any dimension.</exception>
        public void Write(ArraySlice <TTexel> data, uint mipIndex = 0U, uint writeOffsetX = 0U)
        {
            Assure.LessThan(
                mipIndex, NumMips,
                "Can not write to mip level " + mipIndex + ": Only " + NumMips + " present in texture."
                );
            Assure.LessThan(
                data.Length + writeOffsetX,
                Width,
                "Buffer overrun: Please ensure you are not attempting to write past the end of the texture."
                );

            ThrowIfCannotWrite();

            lock (InstanceMutationLock) {
                if (IsDisposed)
                {
                    Logger.Warn("Attempted write manipulation on disposed resource of type: " + GetType().Name);
                    return;
                }

                if (Usage.ShouldUpdateSubresourceRegion())
                {
                    GCHandle pinnedDataHandle = GCHandle.Alloc(data.ContainingArray, GCHandleType.Pinned);
                    try {
                        SubresourceBox subBox = new SubresourceBox(writeOffsetX, writeOffsetX + data.Length);
                        InteropUtils.CallNative(
                            NativeMethods.ResourceFactory_UpdateSubresourceRegion,
                            RenderingModule.DeviceContext,
                            ResourceHandle,
                            GetSubresourceIndex(mipIndex),
                            (IntPtr)(&subBox),
                            pinnedDataHandle.AddrOfPinnedObject() + (int)(data.Offset * TexelSizeBytes),
                            (uint)Size,
                            (uint)Size
                            ).ThrowOnFailure();
                    }
                    finally {
                        pinnedDataHandle.Free();
                    }
                }
                else
                {
                    LosgapSystem.InvokeOnMasterAsync(() => {
                        IntPtr outDataPtr;
                        uint outRowStrideBytes, outSliceStrideBytes;
                        InteropUtils.CallNative(
                            NativeMethods.ResourceFactory_MapSubresource,
                            RenderingModule.DeviceContext,
                            ResourceHandle,
                            GetSubresourceIndex(mipIndex),
                            ResourceMapping.Write,
                            (IntPtr)(&outDataPtr),
                            (IntPtr)(&outRowStrideBytes),
                            (IntPtr)(&outSliceStrideBytes)
                            ).ThrowOnFailure();

                        try {
                            UnsafeUtils.CopyGenericArray(data, outDataPtr + (int)(writeOffsetX * TexelSizeBytes), TexelSizeBytes);
                        }
                        finally {
                            InteropUtils.CallNative(
                                NativeMethods.ResourceFactory_UnmapSubresource,
                                RenderingModule.DeviceContext,
                                ResourceHandle,
                                GetSubresourceIndex(mipIndex)
                                ).ThrowOnFailure();
                        }
                    });
                }
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Performs a <see cref="ResourceUsage.Write"/> on this texture, copying the supplied data to the resource.
        /// </summary>
        /// <param name="data">The data to write.
        /// <see cref="ArraySlice{T}.Length">Length</see> vertices will be copied from the given
        /// array slice. The copy will start from the specified <see cref="ArraySlice{T}.Offset">Offset</see> in the
        /// contained array.
        /// </param>
        /// <param name="dataDesc">The region of the selected <paramref name="mipIndex"/> to write to. The
        /// <see cref="SubresourceBox.Volume"/> of the box must be equal to the <see cref="ArraySlice{T}.Length">Length</see>
        /// parameter of the supplied <paramref name="data"/>.</param>
        /// <param name="mipIndex">The mip level to write to. Only one mip level may be written to at a time. If this texture
        /// is not mipmapped, you must supply a value of <c>0U</c>.</param>
        /// <exception cref="ResourceOperationUnavailableException">Thrown if <see cref="BaseResource.CanDiscardWrite"/> is
        /// <c>false</c>.</exception>
        /// <exception cref="AssuranceFailedException">(Debug only) Thrown if the combination of supplied parameters would
        /// result in writing past the end of the texture in any dimension.</exception>
        public void Write(ArraySlice <TTexel> data, SubresourceBox dataDesc, uint mipIndex = 0U)
        {
            Assure.LessThan(
                mipIndex, NumMips,
                "Can not write to mip level " + mipIndex + ": Only " + NumMips + " present in texture."
                );
            Assure.Equal(
                data.Length,
                dataDesc.Volume,
                "Invalid parameters: Data length must equal the write target region area."
                );
            Assure.LessThanOrEqualTo(
                dataDesc.Left,
                Width,
                "Buffer overrun: Please ensure you are not attempting to write past the end of the texture."
                );
            Assure.LessThanOrEqualTo(
                dataDesc.Right,
                Width,
                "Buffer overrun: Please ensure you are not attempting to write past the end of the texture."
                );
            Assure.LessThanOrEqualTo(
                dataDesc.Top,
                Height,
                "Buffer overrun: Please ensure you are not attempting to write past the end of the texture."
                );
            Assure.LessThanOrEqualTo(
                dataDesc.Bottom,
                Height,
                "Buffer overrun: Please ensure you are not attempting to write past the end of the texture."
                );
            Assure.LessThanOrEqualTo(
                dataDesc.Front,
                Depth,
                "Buffer overrun: Please ensure you are not attempting to write past the end of the texture."
                );
            Assure.LessThanOrEqualTo(
                dataDesc.Back,
                Depth,
                "Buffer overrun: Please ensure you are not attempting to write past the end of the texture."
                );

            ThrowIfCannotWrite();

            lock (InstanceMutationLock) {
                if (IsDisposed)
                {
                    Logger.Warn("Attempted write manipulation on disposed resource of type: " + GetType().Name);
                    return;
                }

                GCHandle pinnedDataHandle = GCHandle.Alloc(data.ContainingArray, GCHandleType.Pinned);

                try {
                    if (Usage.ShouldUpdateSubresourceRegion())
                    {
                        InteropUtils.CallNative(
                            NativeMethods.ResourceFactory_UpdateSubresourceRegion,
                            RenderingModule.DeviceContext,
                            ResourceHandle,
                            GetSubresourceIndex(mipIndex),
                            (IntPtr)(&dataDesc),
                            pinnedDataHandle.AddrOfPinnedObject() + (int)(data.Offset * TexelSizeBytes),
                            dataDesc.Width * TexelSizeBytes,
                            dataDesc.Width * dataDesc.Height * TexelSizeBytes
                            ).ThrowOnFailure();
                    }
                    else
                    {
                        Mutate_MapWrite(pinnedDataHandle, dataDesc, mipIndex);
                    }
                }
                finally {
                    pinnedDataHandle.Free();
                }
            }
        }