public unsafe void TestCreation()
        {
            // Define variables and constants
            const uint NUM_TEXTURES     = 10U;
            const uint TEXEL_SIZE_BYTES = 16;
            const uint TEX_WIDTH        = 512U;
            const uint TEX_HEIGHT       = 128U;
            const uint TEX_DEPTH        = 32U;
            uint       numMipsPerTex    = TextureUtils.GetNumMips(TEX_WIDTH, TEX_HEIGHT, TEX_DEPTH);
            IntPtr     mockDataStart    = new IntPtr(100);

            // Set up context


            // Execute
            InitialResourceDataDesc[] initialDataArray = InitialResourceDataDesc.CreateDataArr(
                mockDataStart,
                NUM_TEXTURES,
                numMipsPerTex,
                TEX_WIDTH,
                TEX_HEIGHT,
                TEX_DEPTH,
                TEXEL_SIZE_BYTES
                );

            // Assert outcome
            Assert.AreEqual((int)(NUM_TEXTURES * numMipsPerTex), initialDataArray.Length);
            for (uint tex = 0U; tex < NUM_TEXTURES; ++tex)
            {
                for (uint mip = 0U; mip < numMipsPerTex; ++mip)
                {
                    InitialResourceDataDesc thisDesc = initialDataArray[numMipsPerTex * tex + mip];
                    IntPtr expectedDataStart         = mockDataStart;
                    expectedDataStart += (int)(TextureUtils.GetSize(TEXEL_SIZE_BYTES, true, TEX_WIDTH, TEX_HEIGHT, TEX_DEPTH) * tex);
                    for (uint i = 0U; i < mip; ++i)
                    {
                        uint mipWidth  = TextureUtils.GetDimensionForMipLevel(TEX_WIDTH, i);
                        uint mipHeight = TextureUtils.GetDimensionForMipLevel(TEX_HEIGHT, i);
                        uint mipDepth  = TextureUtils.GetDimensionForMipLevel(TEX_DEPTH, i);
                        expectedDataStart += (int)TextureUtils.GetSize(TEXEL_SIZE_BYTES, false, mipWidth, mipHeight, mipDepth);
                    }

                    Assert.AreEqual(expectedDataStart, thisDesc.Data);
                    Assert.AreEqual(TextureUtils.GetDimensionForMipLevel(TEX_WIDTH, mip) * TEXEL_SIZE_BYTES, thisDesc.DataRowStrideBytes);
                    Assert.AreEqual(
                        TextureUtils.GetDimensionForMipLevel(TEX_WIDTH, mip)
                        * TextureUtils.GetDimensionForMipLevel(TEX_HEIGHT, mip)
                        * TEXEL_SIZE_BYTES,
                        thisDesc.DataSliceStrideBytes
                        );
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Creates a new <see cref="Texture3D{TTexel}"/> with the supplied builder parameters.
        /// </summary>
        /// <remarks>
        /// In debug mode, this method will check a large number of <see cref="Assure">assurances</see>
        /// on the builder parameters before creating the resource.
        /// </remarks>
        /// <returns>A new <see cref="Texture3D{TTexel}"/>.</returns>
        public unsafe override Texture3D <TTexel> Create()
        {
            Assure.True(Usage != ResourceUsage.Immutable || InitialData != null, "You must supply initial data to an immutable resource.");
            Assure.False(
                (Usage == ResourceUsage.Immutable || Usage == ResourceUsage.DiscardWrite) && permittedBindings == GPUBindings.None,
                "An immutable or discard-write resource with no permitted bindings is useless."
                );
            Assure.False(
                Usage.GetUsage() == 0x3 && permittedBindings != GPUBindings.None,
                "Staging resources can not be bound to the pipeline."
                );
            Assure.False((Usage == ResourceUsage.DiscardWrite || Usage == ResourceUsage.Immutable) &&
                         ((permittedBindings & GPUBindings.RenderTarget) > 0 ||
                          (permittedBindings & GPUBindings.DepthStencilTarget) > 0 ||
                          (permittedBindings & GPUBindings.WritableShaderResource) > 0),
                         "Can not bind an immutable or discard-write texture as a render target or depth stencil target, or as a GPU-writeable shader resource."
                         );

            Assure.GreaterThan(width, 0U, "Please specify a width for the texture.");
            Assure.GreaterThan(height, 0U, "Please specify a height for the texture.");
            Assure.GreaterThan(depth, 0U, "Please specify a depth for the texture.");

            Assure.False(
                mipAllocation && !MathUtils.IsPowerOfTwo(width),
                "Can not create mipmapped texture with any non-power-of-two (NPOT) dimension. " +
                "Dimensions: " + width + "x" + height + "x" + depth + "."
                );
            Assure.False(
                mipAllocation && !MathUtils.IsPowerOfTwo(height),
                "Can not create mipmapped texture with any non-power-of-two (NPOT) dimension. " +
                "Dimensions: " + width + "x" + height + "x" + depth + "."
                );
            Assure.False(
                mipAllocation && !MathUtils.IsPowerOfTwo(depth),
                "Can not create mipmapped texture with any non-power-of-two (NPOT) dimension. " +
                "Dimensions: " + width + "x" + height + "x" + depth + "."
                );
            Assure.False(
                mipAllocation && Usage == ResourceUsage.DiscardWrite,
                "Can not allocate mips on a discard-write texture."
                );
            Assure.False(
                mipGenerationTarget && !mipAllocation,
                "Can not generate mips without allocating space for them."
                );
            Assure.False(
                mipGenerationTarget &&
                ((permittedBindings & GPUBindings.RenderTarget) == 0x0 || (permittedBindings & GPUBindings.ReadableShaderResource) == 0x0),
                "To make a texture a viable mip generation target, it must be created with the RenderTarget and ReadableShaderResource GPU bindings."
                );
            Assure.False(
                mipGenerationTarget && InitialData != null,
                "Can not supply initial data to a mip generation target."
                );
            Assure.True(
                InitialData == null ||
                (InitialData.Value.Length == TextureUtils.GetSizeTexels(mipAllocation, width, height, depth)),
                "Initial data is of incorrect length (" + (InitialData != null ? InitialData.Value.Length : 0) + ") for this resource. " +
                "It should have a length of: " + TextureUtils.GetSizeTexels(mipAllocation, width, height, depth) + "."
                );
            Assure.False(dynamicDetail && Usage.GetUsage() == 0x3, "Can not create a dynamic-detail staging resource.");
            Assure.False(
                (permittedBindings & GPUBindings.DepthStencilTarget) == GPUBindings.DepthStencilTarget &&
                texelFormat != TexelFormat.DSV_FORMAT_CODE,
                "Can not create a depth-stencil target with any texel format other than " + typeof(TexelFormat.DepthStencil).Name + "."
                );

            Texture3DResourceHandle outResourceHandle;
            GCHandle?pinnedInitData   = null;
            GCHandle?pinnedDataHandle = null;
            IntPtr   initialDataPtr   = IntPtr.Zero;

            InitialResourceDataDesc[] dataArr = null;

            if (InitialData != null)
            {
                pinnedInitData = GCHandle.Alloc(InitialData.Value.ContainingArray, GCHandleType.Pinned);

                dataArr = InitialResourceDataDesc.CreateDataArr(
                    pinnedInitData.Value.AddrOfPinnedObject() + (int)(InitialData.Value.Offset * texelSizeBytes),
                    1U,
                    numMips,
                    width,
                    height,
                    depth,
                    texelSizeBytes
                    );

                pinnedDataHandle = GCHandle.Alloc(dataArr, GCHandleType.Pinned);
                initialDataPtr   = pinnedDataHandle.Value.AddrOfPinnedObject();
            }

            try {
                InteropUtils.CallNative(NativeMethods.ResourceFactory_CreateTexture3D,
                                        RenderingModule.Device,
                                        width,
                                        height,
                                        depth,
                                        (InteropBool)mipAllocation,
                                        texelFormat,
                                        Usage.GetUsage(),
                                        Usage.GetCPUUsage(),
                                        (PipelineBindings)permittedBindings,
                                        (InteropBool)mipGenerationTarget,
                                        (InteropBool)dynamicDetail,
                                        initialDataPtr,
                                        dataArr != null ? (uint)dataArr.Length : 0U,
                                        (IntPtr)(&outResourceHandle)
                                        ).ThrowOnFailure();
            }
            finally {
                if (pinnedDataHandle != null)
                {
                    pinnedDataHandle.Value.Free();
                }
                if (pinnedInitData != null)
                {
                    pinnedInitData.Value.Free();
                }
            }

            return(new Texture3D <TTexel>(
                       outResourceHandle,
                       Usage,
                       TextureUtils.GetSize(texelSizeBytes, mipAllocation, width, height, depth),
                       permittedBindings,
                       mipGenerationTarget,
                       dynamicDetail,
                       width,
                       height,
                       depth,
                       texelSizeBytes,
                       mipAllocation,
                       numMips,
                       0U
                       ));
        }