/// <summary> /// Creates a new <see cref="IndexBuffer"/> 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="IndexBuffer"/>.</returns> public unsafe override IndexBuffer Create() { Assure.True(Usage != ResourceUsage.Immutable || InitialData != null, "You must supply initial data to an immutable resource."); Assure.GreaterThan(length, 0U, "Can not create an index buffer with 0 indices."); GCHandle?pinnedArrayHandle = null; IntPtr initialDataPtr = IntPtr.Zero; if (InitialData != null) { pinnedArrayHandle = GCHandle.Alloc(InitialData.Value.ContainingArray, GCHandleType.Pinned); initialDataPtr = pinnedArrayHandle.Value.AddrOfPinnedObject() + (IndexBuffer.INDEX_SIZE_BYTES * (int)InitialData.Value.Offset); } try { BufferResourceHandle outResourceHandle; InteropUtils.CallNative(NativeMethods.ResourceFactory_CreateIndexBuffer, RenderingModule.Device, length, Usage.GetUsage(), Usage.GetCPUUsage(), initialDataPtr, (IntPtr)(&outResourceHandle) ).ThrowOnFailure(); return(new IndexBuffer(outResourceHandle, Usage, length)); } finally { if (pinnedArrayHandle != null) { pinnedArrayHandle.Value.Free(); } } }
/// <summary> /// Creates a new <see cref="Buffer{TElement}"/> 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="Buffer{TElement}"/>.</returns> public unsafe override Buffer <TElement> 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.GreaterThan(length, 0U, "Can not create a buffer with 0 elements."); InteropBool isStructured = (BaseResource.GetFormatForType(typeof(TElement)) == ResourceFormat.Unknown); InteropBool allowRawAccess = !isStructured && (int)(permittedBindings & (GPUBindings.WritableShaderResource | GPUBindings.ReadableShaderResource)) != 0; GCHandle?pinnedArrayHandle = null; IntPtr initialDataPtr = IntPtr.Zero; try { int elementSizeBytes = UnsafeUtils.SizeOf <TElement>(); if (InitialData != null) { pinnedArrayHandle = GCHandle.Alloc(InitialData.Value.ContainingArray, GCHandleType.Pinned); initialDataPtr = pinnedArrayHandle.Value.AddrOfPinnedObject() + (elementSizeBytes * (int)InitialData.Value.Offset); } BufferResourceHandle outResourceHandle; InteropUtils.CallNative(NativeMethods.ResourceFactory_CreateBuffer, RenderingModule.Device, (uint)elementSizeBytes, length, Usage.GetUsage(), Usage.GetCPUUsage(), (PipelineBindings)permittedBindings, isStructured, allowRawAccess, initialDataPtr, (IntPtr)(&outResourceHandle) ).ThrowOnFailure(); return(new Buffer <TElement>(outResourceHandle, Usage, (uint)elementSizeBytes, length, permittedBindings, isStructured)); } finally { if (pinnedArrayHandle != null) { pinnedArrayHandle.Value.Free(); } } }
/// <summary> /// Creates a new <see cref="ConstantBuffer{TConstants}"/> 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="ConstantBuffer{TConstants}"/>.</returns> public unsafe override ConstantBuffer <TConstants> Create() { uint structSizeBytes = (uint)UnsafeUtils.SizeOf <TConstants>(); byte *initValueStackCopy = stackalloc byte[(int)structSizeBytes]; UnsafeUtils.WriteGenericToPtr((IntPtr)initValueStackCopy, InitialData, structSizeBytes); BufferResourceHandle outResourceHandle; InteropUtils.CallNative(NativeMethods.ResourceFactory_CreateConstantBuffer, RenderingModule.Device, structSizeBytes, Usage.GetUsage(), Usage.GetCPUUsage(), (IntPtr)initValueStackCopy, (IntPtr)(&outResourceHandle) ).ThrowOnFailure(); return(new ConstantBuffer <TConstants>(outResourceHandle, Usage, structSizeBytes)); }
/// <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 )); }