public unsafe void SetMaterialConstantValue <TValue>(ConstantBufferBinding binding, TValue value) where TValue : struct { Assure.True(Shader.ContainsBinding(binding), "Binding is not attributed to the FragmentShader set for this material."); Assure.True( binding.GetBoundResource() is ConstantBuffer <TValue>, "Expected a resource of type 'ConstantBuffer<" + typeof(TValue).Name + ">' set at " + binding + ", but instead found " + binding.GetBoundResource().ToStringNullSafe("no binding") + "." ); Assure.True( binding.GetBoundResource().CanDiscardWrite, "Given shader resource (" + binding.GetBoundResource() + ") must have discard-write capability." ); if (cbufferValuePtrs.ContainsKey(binding)) { Marshal.FreeHGlobal(cbufferValuePtrs[binding]); } IntPtr valuePtr = Marshal.AllocHGlobal(new IntPtr(binding.BufferSizeBytes)); UnsafeUtils.WriteGenericToPtr(valuePtr, value, binding.BufferSizeBytes); using (RenderingModule.RenderStateBarrier.AcquirePermit(withLock: instanceMutationLock)) { cbufferValuePtrs[binding] = valuePtr; fragmentShaderResources.SetValue(binding, valuePtr); } }
public ModelInstanceHandle AllocateInstance(uint materialIndex, uint modelIndex, uint sceneLayerIndex, Transform initialTransform) { using (RenderingModule.RenderStateBarrier.AcquirePermit(withLock: instanceMutationLock)) { MIDArray midArray = materialMap.GetOrCreate(materialIndex, createNewMIDArrayAct); ModelInstanceData *data = midArray.Data; for (uint i = midArray.Length - 1U; i < midArray.Length; --i) { if (!data[i].InUse) { data[i] = new ModelInstanceData(modelIndex, sceneLayerIndex, initialTransform); return(new ModelInstanceHandle(this, materialIndex, i)); } } // MIDArray is full, so resize... uint newSize = midArray.Length << 1; uint numBytes = (uint)sizeof(ModelInstanceData) * newSize; uint oldNumBytes = (uint)sizeof(ModelInstanceData) * midArray.Length; if (midArray.Length >= MAX_SIZE_BEFORE_LINEAR_GROWTH) { newSize = midArray.Length + LINEAR_GROWTH_AMOUNT; } ModelInstanceData *newData = (ModelInstanceData *)Marshal.AllocHGlobal(new IntPtr(numBytes)); UnsafeUtils.MemCopy((IntPtr)data, (IntPtr)newData, oldNumBytes); Marshal.FreeHGlobal((IntPtr)data); UnsafeUtils.ZeroMem(((IntPtr)newData) + (int)oldNumBytes, numBytes - oldNumBytes); materialMap[materialIndex] = new MIDArray(newData, newSize); newData[midArray.Length] = new ModelInstanceData(modelIndex, sceneLayerIndex, initialTransform); return(new ModelInstanceHandle(this, materialIndex, midArray.Length)); } }
internal VertexBufferBuilder(ResourceUsage usage, uint length, ArraySlice <TVertex>?initialData) : base(usage, initialData) { Assure.True(typeof(TVertex).IsBlittable()); Assure.GreaterThan(UnsafeUtils.SizeOf <TVertex>(), 0); this.length = length; }
private static IntPtr AllocAndZeroTemp(uint numBytes) { IntPtr result = RenderCommandTempMemPool.GetLocalPool().Reserve(numBytes); UnsafeUtils.ZeroMem(result, numBytes); return(result); }
/// <summary> /// Writes the contents of an array to the buffer. More efficient with /// large arrays. /// </summary> /// <typeparam name="T">The type of element to write.</typeparam> /// <param name="array">The values to write.</param> public unsafe void Write <T>(T[] array) where T : unmanaged { var length = UnsafeUtils.LengthInBytes(array); if (length > 0) { var handle = GCHandle.Alloc(array, GCHandleType.Pinned); try { // ensure there is enough space for the new content if (BytesRemaining < length) { GrowBuffer(length); } // start from where we last finished writting var src = handle.AddrOfPinnedObject(); // copy the memory using an optimal method Buffer.MemoryCopy(src.ToPointer(), m_ptr.ToPointer(), BytesRemaining, length); m_ptr += length; } finally { // always free the handle, even if an exception occurs handle.Free(); } } }
public unsafe void TestDepthStencilTargetWithWindow() { Window depthStencilWindow = new Window("Test window"); RenderTargetViewHandle outRTV; DepthStencilViewHandle outDSV; depthStencilWindow.GetWindowRTVAndDSV(out outRTV, out outDSV); RenderCommand testCommand = RenderCommand.ClearDepthStencil(depthStencilWindow); Assert.AreEqual(RenderCommandInstruction.ClearDepthStencil, testCommand.Instruction); Assert.AreEqual( outDSV, UnsafeUtils.Reinterpret <IntPtr, DepthStencilViewHandle>(new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long))), sizeof(DepthStencilViewHandle)) ); depthStencilWindow.Close(); LosgapSystem.InvokeOnMaster(() => { }); // Wait for the window to be closed testCommand = RenderCommand.ClearDepthStencil(depthStencilWindow); Assert.AreEqual(RenderCommandInstruction.NoOperation, testCommand.Instruction); #if !DEVELOPMENT && !RELEASE try { RenderCommand.ClearDepthStencil(null as Window); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public unsafe void TestSetRenderTargetsWithWindow() { Window renderTargetWindow = new Window("Test window"); RenderTargetViewHandle outRTV; DepthStencilViewHandle outDSV; renderTargetWindow.GetWindowRTVAndDSV(out outRTV, out outDSV); RenderCommand testCommand = RenderCommand.SetRenderTargets(renderTargetWindow); Assert.AreEqual(RenderCommandInstruction.SetRenderTargets, testCommand.Instruction); Assert.AreEqual( outRTV, ((RenderTargetViewHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long))))[0] ); Assert.AreEqual((RenderCommandArgument)(IntPtr)(ResourceViewHandle)outDSV, testCommand.Arg2); Assert.AreEqual((RenderCommandArgument)1U, testCommand.Arg3); renderTargetWindow.Close(); LosgapSystem.InvokeOnMaster(() => { }); // Wait for the window to be closed testCommand = RenderCommand.SetRenderTargets(renderTargetWindow); Assert.AreEqual(RenderCommandInstruction.NoOperation, testCommand.Instruction); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetRenderTargets(null as Window); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
private MIDArray CreateNewMIDArray(uint materialIndex) { uint numBytes = (uint)sizeof(ModelInstanceData) * INITIAL_INSTANCE_ALLOCATION; ModelInstanceData *data = (ModelInstanceData *)Marshal.AllocHGlobal(new IntPtr(numBytes)); UnsafeUtils.ZeroMem((IntPtr)data, numBytes); return(new MIDArray(data, INITIAL_INSTANCE_ALLOCATION)); }
internal BufferBuilder(ResourceUsage usage, uint length, GPUBindings permittedBindings, ArraySlice <TElement>?initialData) : base(usage, initialData) { Assure.True(typeof(TElement).IsBlittable()); Assure.GreaterThan(UnsafeUtils.SizeOf <TElement>(), 0); this.length = length; this.permittedBindings = permittedBindings; }
public static RenderCommand DiscardWriteShaderConstantBuffer(ConstantBufferBinding binding, IntPtr valuePtr) { Assure.NotNull(binding); Assure.NotEqual(valuePtr, IntPtr.Zero, "valuePtr must not be IntPtr.Zero!"); Assure.False(binding.IsDisposed || binding.GetBoundResource().IsDisposed, "Given binding or its resource was disposed."); IntPtr cbufferValPtr = AllocAndZeroTemp(binding.BufferSizeBytes); UnsafeUtils.MemCopy(valuePtr, cbufferValPtr, binding.BufferSizeBytes); return(new RenderCommand(RenderCommandInstruction.CBDiscardWrite, (IntPtr)binding.GetBoundResource().ResourceHandle, cbufferValPtr, binding.BufferSizeBytes)); }
/// <summary> /// Gets or sets the data at the requested co-ordinates. /// </summary> /// <remarks> /// For reading/writing single elements, using the this member is recommended, but may be slow when attempting /// to copy large sections of the data. In these circumstances, consider using something like /// <see cref="UnsafeUtils.CopyGenericArray{T}(Ophidian.Losgap.ArraySlice{T},System.IntPtr,uint)"/> / /// <see cref="UnsafeUtils.CopyGenericArray{T}(System.IntPtr,Ophidian.Losgap.ArraySlice{T},uint)"/> in combination with the /// <see cref="Data"/> member. /// </remarks> /// <param name="u">The u-coordinate to copy.</param> /// <returns>A copy of the data at the requested co-ordinate.</returns> public T this[uint u] { get { Assure.LessThan(u, Width, "Index out of bounds: u"); return(UnsafeUtils.ReadGenericFromPtr <T>(Data + (int)(sizeOfT * u), sizeOfT)); } set { Assure.LessThan(u, Width, "Index out of bounds: u"); UnsafeUtils.WriteGenericToPtr(Data + (int)(sizeOfT * u), value, sizeOfT); } }
byte[] IBuffer.Read() { return(LosgapSystem.InvokeOnMaster(() => { byte[] result = new byte[Size]; Mutate_MapRead( data => UnsafeUtils.CopyGenericArray <byte>(data, result, sizeof(byte)), ResourceMapping.Read ); return result; })); }
/// <summary> /// Performs a <see cref="ResourceUsage.StagingRead"/> on this texture, copying all the data from every mip level and /// concatenating it in to a single <typeparamref name="TTexel"/> array. /// </summary> /// <returns>An array of all texels in this resource, ordered by ascending mip level.</returns> /// <exception cref="ResourceOperationUnavailableException">Thrown if <see cref="BaseResource.CanRead"/> is /// <c>false</c>.</exception> public override TTexel[] ReadAll() { ThrowIfCannotRead(); return(LosgapSystem.InvokeOnMaster(() => { TTexel[] result = new TTexel[SizeTexels]; lock (InstanceMutationLock) { if (IsDisposed) { Logger.Warn("Attempted read manipulation on disposed resource of type: " + GetType().Name); return result; } GCHandle pinnedResult = GCHandle.Alloc(result, GCHandleType.Pinned); try { int offsetBytes = 0; for (uint i = 0; i < NumMips; ++i) { IntPtr outDataPtr; uint outRowStrideBytes, outSliceStrideBytes; InteropUtils.CallNative( NativeMethods.ResourceFactory_MapSubresource, RenderingModule.DeviceContext, ResourceHandle, GetSubresourceIndex(i), ResourceMapping.Read, (IntPtr)(&outDataPtr), (IntPtr)(&outRowStrideBytes), (IntPtr)(&outSliceStrideBytes) ).ThrowOnFailure(); try { uint numBytes = MipWidth(i) * TexelSizeBytes; UnsafeUtils.MemCopy(outDataPtr, pinnedResult.AddrOfPinnedObject() + offsetBytes, numBytes); offsetBytes += (int)numBytes; } finally { InteropUtils.CallNative( NativeMethods.ResourceFactory_UnmapSubresource, RenderingModule.DeviceContext, ResourceHandle, GetSubresourceIndex(i) ).ThrowOnFailure(); } } } finally { pinnedResult.Free(); } } return result; })); }
/// <summary> /// Performs a <see cref="ResourceUsage.DiscardWrite"/> on this buffer. A discard-write is a faster write that first discards /// the old data, then writes the new data. /// </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="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> /// <param name="writeOffsetX">The X-dimension offset in to the selected <paramref name="mipIndex"/> to write the data to.</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 DiscardWrite(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.LessThanOrEqualTo( data.Length + writeOffsetX, Width, "Buffer overrun: Please ensure you are not attempting to write past the end of the texture." ); ThrowIfCannotDiscardWrite(); 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 { IntPtr outDataPtr; uint outRowStrideBytes, outSliceStrideBytes; InteropUtils.CallNative( NativeMethods.ResourceFactory_MapSubresource, RenderingModule.DeviceContext, ResourceHandle, GetSubresourceIndex(mipIndex), ResourceMapping.WriteDiscard, (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(); } } finally { pinnedDataHandle.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> /// Gets or sets the data at the requested co-ordinates. /// </summary> /// <remarks> /// For reading/writing single elements, using this member is recommended, but may be slow when attempting /// to copy large sections of the data. In these circumstances, consider using something like /// <see cref="UnsafeUtils.CopyGenericArray{T}(Ophidian.Losgap.ArraySlice{T},System.IntPtr,uint)"/> / /// <see cref="UnsafeUtils.CopyGenericArray{T}(System.IntPtr,Ophidian.Losgap.ArraySlice{T},uint)"/> in combination with the /// <see cref="Data"/> member. /// </remarks> /// <param name="u">The u-coordinate to copy.</param> /// <param name="v">The v-coordinate to copy.</param> /// <returns>A copy of the data at the requested co-ordinate.</returns> public T this[uint u, uint v] { get { Assure.LessThan(u, Width, "Index out of bounds: u"); Assure.LessThan(v, Height, "Index out of bounds: v"); return(UnsafeUtils.ReadGenericFromPtr <T>(Data + (int)(u * sizeOfT + v * rowStrideBytes), sizeOfT)); } set { Assure.LessThan(u, Width, "Index out of bounds: u"); Assure.LessThan(v, Height, "Index out of bounds: v"); UnsafeUtils.WriteGenericToPtr(Data + (int)(u * sizeOfT + v * rowStrideBytes), value, sizeOfT); } }
internal Texture1DBuilder(ResourceUsage usage, ArraySlice <TTexel>?initialData, GPUBindings permittedBindings, uint width, bool mipAllocation, bool mipGenerationTarget, bool dynamicDetail) : base(usage, initialData) { Assure.True(typeof(TTexel).IsBlittable()); Assure.GreaterThan(UnsafeUtils.SizeOf <TTexel>(), 0); this.permittedBindings = permittedBindings; this.width = width; this.mipAllocation = mipAllocation; this.mipGenerationTarget = mipGenerationTarget; this.dynamicDetail = dynamicDetail; this.numMips = mipAllocation ? TextureUtils.GetNumMips(width) : 1U; }
void IBuffer.ReadWrite(Action <byte[]> readWriteAction) { LosgapSystem.InvokeOnMaster(() => Mutate_MapRead( dataAsPtr => { byte[] dataAsArray = new byte[Size]; UnsafeUtils.CopyGenericArray <byte>(dataAsPtr, dataAsArray, sizeof(byte)); readWriteAction(dataAsArray); UnsafeUtils.CopyGenericArray <byte>(dataAsArray, dataAsPtr, sizeof(byte)); }, ResourceMapping.ReadWrite ) ); }
public static RenderCommand DiscardWriteShaderConstantBuffer <T>(Buffer <T> buffer, ArraySlice <T> data, uint sizeofT) where T : struct { var dataSize = data.Length * sizeofT; IntPtr cbufferValPtr = AllocAndZeroTemp(dataSize); GCHandle pinnedDataHandle = GCHandle.Alloc(data.ContainingArray, GCHandleType.Pinned); try { UnsafeUtils.MemCopy(pinnedDataHandle.AddrOfPinnedObject(), cbufferValPtr, dataSize); } finally { pinnedDataHandle.Free(); } return(new RenderCommand(RenderCommandInstruction.BufferWrite, (IntPtr)buffer.ResourceHandle, cbufferValPtr, dataSize)); }
public Texture2DBuilder <TTexel> WithInitialData(ArraySlice <byte> initialDataRaw) { var handle = GCHandle.Alloc(initialDataRaw.ContainingArray, GCHandleType.Pinned); TTexel[] actualInitData = new TTexel[TextureUtils.GetSizeTexels(mipAllocation, width, height)]; try { UnsafeUtils.CopyGenericArray <TTexel>(handle.AddrOfPinnedObject() + (int)initialDataRaw.Offset, actualInitData, texelSizeBytes); } finally { handle.Free(); } return(WithInitialData(actualInitData)); }
private unsafe void ResizeList() { uint newListLen = CurListLen + LIST_SIZE_INCREMENT; GC.RemoveMemoryPressure(sizeof(RenderCommand) * CurListLen); AlignedAllocation <RenderCommand> newListSpace = AlignedAllocation <RenderCommand> .AllocArray(LIST_ALIGNMENT, newListLen); GC.AddMemoryPressure(sizeof(RenderCommand) * CurListLen); UnsafeUtils.MemCopy(RenderCommandList.AlignedPointer, newListSpace.AlignedPointer, (uint)sizeof(RenderCommand) * CurListLen); CurListLen = newListLen; RenderCommandList.Dispose(); RenderCommandList = newListSpace; }
/// <summary> /// Performs a <see cref="ResourceUsage.StagingRead"/> on this texture, /// returning a view of the texel data at the given <paramref name="mipIndex"/>. /// </summary> /// <param name="mipIndex">The mip index to read data from. Must be less than <see cref="ITexture.NumMips"/>.</param> /// <returns>A <see cref="TexelArray1D{TTexel}"/> of the data.</returns> /// <exception cref="ResourceOperationUnavailableException">Thrown if <see cref="BaseResource.CanRead"/> is /// <c>false</c>.</exception> public TexelArray1D <TTexel> Read(uint mipIndex) { Assure.LessThan( mipIndex, NumMips, "Can not read from mip level " + mipIndex + ": Only " + NumMips + " present in texture." ); ThrowIfCannotRead(); TTexel[] data = LosgapSystem.InvokeOnMaster(() => { TTexel[] result = new TTexel[MipWidth(mipIndex)]; lock (InstanceMutationLock) { if (IsDisposed) { Logger.Warn("Attempted read manipulation on disposed resource of type: " + GetType().Name); return(result); } IntPtr outDataPtr; uint outRowStrideBytes, outSliceStrideBytes; InteropUtils.CallNative( NativeMethods.ResourceFactory_MapSubresource, RenderingModule.DeviceContext, ResourceHandle, GetSubresourceIndex(mipIndex), ResourceMapping.Read, (IntPtr)(&outDataPtr), (IntPtr)(&outRowStrideBytes), (IntPtr)(&outSliceStrideBytes) ).ThrowOnFailure(); try { UnsafeUtils.CopyGenericArray <TTexel>(outDataPtr, result, TexelSizeBytes); return(result); } finally { InteropUtils.CallNative( NativeMethods.ResourceFactory_UnmapSubresource, RenderingModule.DeviceContext, ResourceHandle, GetSubresourceIndex(mipIndex) ).ThrowOnFailure(); } } }); return(new TexelArray1D <TTexel>(data)); }
public byte[] ReadRaw() { byte[] dst = new byte[Size]; TTexel[] src = ReadAll(); var dstHandle = GCHandle.Alloc(dst, GCHandleType.Pinned); try { UnsafeUtils.CopyGenericArray <TTexel>(src, dstHandle.AddrOfPinnedObject(), TexelSizeBytes); } finally { dstHandle.Free(); } return(dst); }
public unsafe void TestDrawIndexedInstanced() { RenderCommand testCommand = RenderCommand.DrawIndexedInstanced(1, 2U, 3U, 4U, 5U); Assert.AreEqual(RenderCommandInstruction.DrawIndexedInstanced, testCommand.Instruction); Assert.AreEqual((RenderCommandArgument)1, testCommand.Arg1); ulong arg2AsUlong = UnsafeUtils.Reinterpret <RenderCommandArgument, ulong>(testCommand.Arg2, sizeof(ulong)); uint *arg23Ptr = (uint *)&arg2AsUlong; Assert.AreEqual(2U, arg23Ptr[0]); Assert.AreEqual(3U, arg23Ptr[1]); ulong arg3AsUlong = UnsafeUtils.Reinterpret <RenderCommandArgument, ulong>(testCommand.Arg3, sizeof(ulong)); uint *arg45Ptr = (uint *)&arg3AsUlong; Assert.AreEqual(4U, arg45Ptr[0]); Assert.AreEqual(5U, arg45Ptr[1]); }
private void Mutate_MapWrite(IntPtr dataPtr, uint numBytesToWrite, uint writeOffset, ResourceMapping writeType) { lock (InstanceMutationLock) { if (IsDisposed) { Logger.Warn("Attempted write manipulation on disposed resource of type: " + GetType().Name); return; } IntPtr outDataPtr; uint outUnused; char *failReason = stackalloc char[InteropUtils.MAX_INTEROP_FAIL_REASON_STRING_LENGTH + 1]; bool success = NativeMethods.ResourceFactory_MapSubresource( (IntPtr)failReason, RenderingModule.DeviceContext, ResourceHandle, 0U, writeType, (IntPtr)(&outDataPtr), (IntPtr)(&outUnused), (IntPtr)(&outUnused) ); if (!success) { throw new NativeOperationFailedException(Marshal.PtrToStringUni((IntPtr)failReason)); } UnsafeUtils.MemCopy(dataPtr, outDataPtr + (int)writeOffset, numBytesToWrite); char *failReason2 = stackalloc char[InteropUtils.MAX_INTEROP_FAIL_REASON_STRING_LENGTH + 1]; bool success2 = NativeMethods.ResourceFactory_UnmapSubresource( (IntPtr)failReason, RenderingModule.DeviceContext, ResourceHandle, 0U ); if (!success2) { throw new NativeOperationFailedException(Marshal.PtrToStringUni((IntPtr)failReason2)); } } }
/// <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)); }
public unsafe void TestDiscardWriteShaderConstantBuffer() { ConstantBuffer <Vector4> cb = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite); ConstantBufferBinding cbb = new ConstantBufferBinding(0U, "CB0", cb); Vector4 initialValue = Vector4.FORWARD; cbb.SetValue((byte *)(&initialValue)); RenderCommand testCommand = RenderCommand.DiscardWriteShaderConstantBuffer(cbb, cbb.CurValuePtr); Assert.AreEqual(RenderCommandInstruction.CBDiscardWrite, testCommand.Instruction); Assert.AreEqual((RenderCommandArgument)(IntPtr)cbb.GetBoundResource().ResourceHandle, testCommand.Arg1); Assert.AreEqual(*((Vector4 *)cbb.CurValuePtr), *((Vector4 *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg2, sizeof(long))))); Assert.AreEqual((RenderCommandArgument)cbb.BufferSizeBytes, testCommand.Arg3); #if !DEVELOPMENT && !RELEASE try { RenderCommand.DiscardWriteShaderConstantBuffer(null, cbb.CurValuePtr); Assert.Fail(); } catch (AssuranceFailedException) { } try { RenderCommand.DiscardWriteShaderConstantBuffer(cbb, IntPtr.Zero); Assert.Fail(); } catch (AssuranceFailedException) { } #endif (cbb as IDisposable).Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.DiscardWriteShaderConstantBuffer(cbb, cbb.CurValuePtr); Assert.Fail(); } catch (AssuranceFailedException) { } #endif cb.Dispose(); }
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 unsafe void SetShaderConstantBuffers() { ConstantBuffer <Vector4> cb0 = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite); ConstantBuffer <Matrix> cb1 = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite); Shader shader = new FragmentShader( @"Tests\SimpleFS.cso", new ConstantBufferBinding(0U, "CB0", cb0), new ConstantBufferBinding(1U, "CB1", cb1) ); RenderCommand testCommand = RenderCommand.SetShaderConstantBuffers(shader); Assert.AreEqual(RenderCommandInstruction.FSSetCBuffers, testCommand.Instruction); ResourceHandle *resHandleArray = (ResourceHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long))); Assert.AreEqual(cb0.ResourceHandle, resHandleArray[0]); Assert.AreEqual(cb1.ResourceHandle, resHandleArray[1]); Assert.AreEqual((RenderCommandArgument)shader.NumConstantBufferSlots, testCommand.Arg2); shader.Dispose(); cb1.Dispose(); cb0.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderConstantBuffers(null); Assert.Fail(); } catch (AssuranceFailedException) { } try { RenderCommand.SetShaderConstantBuffers(shader); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public static AlignedAllocation <T> AllocArray(long alignment, uint arrLen) { Assure.GreaterThan(alignment, 0L, "Alignment must be positive."); uint sizeOfT = (uint)UnsafeUtils.SizeOf <T>(); uint reservationSize = sizeOfT * arrLen; IntPtr allocStart = Marshal.AllocHGlobal(new IntPtr(reservationSize + alignment - 1)); long allocationOffset = (long)allocStart % alignment; IntPtr alignedStart; if (allocationOffset == 0L) { alignedStart = allocStart; } else { alignedStart = allocStart + (int)(alignment - allocationOffset); } return(new AlignedAllocation <T>(alignedStart, sizeOfT, allocStart)); }