public static unsafe PhysicsShapeHandle CreateConcaveHullShape(IEnumerable <Vector3> vertices, IEnumerable <int> indices, CollisionShapeOptionsDesc shapeOptions, string acdFilePath) { return(LosgapSystem.InvokeOnMaster(() => { AlignedAllocation <CollisionShapeOptionsDesc> shapeOptionsAligned = new AlignedAllocation <CollisionShapeOptionsDesc>(16L, (uint)sizeof(CollisionShapeOptionsDesc)); *((CollisionShapeOptionsDesc *)shapeOptionsAligned.AlignedPointer) = shapeOptions; Vector3 *verticesLocal = stackalloc Vector3[vertices.Count()]; int *indicesLocal = stackalloc int[indices.Count()]; int numVertices = 0; int numIndices = 0; foreach (Vector3 vertex in vertices) { verticesLocal[numVertices++] = vertex; } foreach (int index in indices) { indicesLocal[numIndices++] = index; } PhysicsShapeHandle result; InteropUtils.CallNative( NativeMethods.PhysicsManager_CreateConcaveHullShape, (IntPtr)verticesLocal, numVertices, (IntPtr)indicesLocal, numIndices, shapeOptionsAligned.AlignedPointer, acdFilePath, (IntPtr)(&result) ).ThrowOnFailure(); shapeOptionsAligned.Dispose(); return result; })); }
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 }
public void TestWrite() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants IBuffer res = BufferFactory.NewBuffer <int>() .WithUsage(ResourceUsage.Write) .WithLength(100) .Create(); IBuffer copyDest = (res as Buffer <int>).Clone() .WithUsage(ResourceUsage.StagingRead) .WithPermittedBindings(GPUBindings.None) .Create(); // Set up context // Execute Assert.IsTrue(res.CanWrite); res.Write(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 10U); res.CopyTo(copyDest); // Assert outcome byte[] readData = copyDest.Read(); for (int i = 10; i < 20; ++i) { Assert.AreEqual(i - 9, readData[i]); } res.Dispose(); copyDest.Dispose(); }); }
internal unsafe static PhysicsBodyHandle CreateRigidBody(PhysicsShapeHandle shapeHandle, float mass, bool alwaysActive, bool forceIntransigence, bool collideOnlyAgainstWorld, bool collideAgainstDynamicsOnly, IntPtr translationPtr, IntPtr rotationPtr, IntPtr shapeOffsetPtr) { Assure.GreaterThanOrEqualTo(mass, 0f); if (collideOnlyAgainstWorld && collideAgainstDynamicsOnly) { throw new ArgumentException("Can't collide against world and only dynamics simultaneously."); } return(LosgapSystem.InvokeOnMaster(() => { PhysicsBodyHandle result; InteropUtils.CallNative( NativeMethods.PhysicsManager_CreateRigidBody, translationPtr, rotationPtr, shapeOffsetPtr, shapeHandle, mass, (InteropBool)alwaysActive, (InteropBool)forceIntransigence, (InteropBool)collideOnlyAgainstWorld, (InteropBool)collideAgainstDynamicsOnly, (IntPtr)(&result) ).ThrowOnFailure(); return result; })); }
public void TestGenerateMips() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants const uint WIDTH_TX = 256U; const uint HEIGHT_TX = 128U; const uint ARR_LEN = 4U; Texture2DArray <TexelFormat.RGBA8UNorm> sourceTex = TextureFactory.NewTexture2D <TexelFormat.RGBA8UNorm>() .WithWidth(WIDTH_TX) .WithHeight(HEIGHT_TX) .WithMipAllocation(true) .WithMipGenerationTarget(true) .WithPermittedBindings(GPUBindings.ReadableShaderResource | GPUBindings.RenderTarget) .WithUsage(ResourceUsage.Write) .CreateArray(ARR_LEN); Texture2DArray <TexelFormat.RGBA8UNorm> copyDestTex = sourceTex.Clone() .WithUsage(ResourceUsage.StagingRead) .WithPermittedBindings(GPUBindings.None) .WithMipGenerationTarget(false) .CreateArray(ARR_LEN); // Set up context for (uint u = 0U; u < ARR_LEN; u++) { sourceTex[u].Write( // ReSharper disable PossibleLossOfFraction No one cares Enumerable.Range(0, (int)TextureUtils.GetSizeTexels(false, WIDTH_TX, HEIGHT_TX)) .Select(i => new TexelFormat.RGBA8UNorm { R = 0f, G = 0.33f, B = 0.67f, A = 1f }).ToArray(), // ReSharper restore PossibleLossOfFraction new SubresourceBox(0U, WIDTH_TX, 0U, HEIGHT_TX), 0U ); } // Execute sourceTex.GenerateMips(); sourceTex.CopyTo(copyDestTex); // Assert outcome for (uint u = 0U; u < ARR_LEN; u++) { for (uint i = 1U; i < TextureUtils.GetNumMips(WIDTH_TX, HEIGHT_TX); ++i) { IEnumerable <TexelFormat.RGBA8UNorm> outData = copyDestTex[u].Read(i); // ReSharper disable CompareOfFloatsByEqualityOperator Exact equality is fine here Assert.IsTrue(outData.Any(texel => texel.R != 0f || texel.G != 0f || texel.B != 0f || texel.A != 0f)); // ReSharper restore CompareOfFloatsByEqualityOperator } } sourceTex.Dispose(); copyDestTex.Dispose(); }); }
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(); }); }
public void TestCopyTo() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants const uint WIDTH_TX = 512U; const uint NUM_TEXELS_TO_COPY = 25U; const uint FIRST_TEXEL_TO_COPY = 25U; const uint SRC_MIP_INDEX = 1U; const uint DST_MIP_INDEX = 3U; const uint DST_WRITE_OFFSET = 15U; const uint DATA_VALUE_START_R = 512U + FIRST_TEXEL_TO_COPY; Texture1D <TexelFormat.RGBA32Int> srcTex = TextureFactory.NewTexture1D <TexelFormat.RGBA32Int>() .WithDynamicDetail(false) .WithInitialData( Enumerable.Range(0, (int)TextureUtils.GetSizeTexels(true, WIDTH_TX)) .Select(i => new TexelFormat.RGBA32Int { R = i, G = i * 2, B = i * 3, A = i * 4 }) .ToArray() ) .WithMipAllocation(true) .WithMipGenerationTarget(false) .WithPermittedBindings(GPUBindings.ReadableShaderResource) .WithUsage(ResourceUsage.Immutable) .WithWidth(WIDTH_TX); // Set up context // Execute Texture1D <TexelFormat.RGBA32Int> dstTex = srcTex.Clone() .WithUsage(ResourceUsage.StagingRead) .WithPermittedBindings(GPUBindings.None); srcTex.CopyTo( dstTex, new SubresourceBox(FIRST_TEXEL_TO_COPY, FIRST_TEXEL_TO_COPY + NUM_TEXELS_TO_COPY), SRC_MIP_INDEX, DST_MIP_INDEX, DST_WRITE_OFFSET ); // Assert outcome TexelArray1D <TexelFormat.RGBA32Int> copiedData = dstTex.Read(DST_MIP_INDEX); for (int i = 0; i < NUM_TEXELS_TO_COPY; ++i) { Assert.AreEqual(DATA_VALUE_START_R + i, copiedData[i + (int)DST_WRITE_OFFSET].R); Assert.AreEqual((DATA_VALUE_START_R + i) * 2, copiedData[i + (int)DST_WRITE_OFFSET].G); Assert.AreEqual((DATA_VALUE_START_R + i) * 3, copiedData[i + (int)DST_WRITE_OFFSET].B); Assert.AreEqual((DATA_VALUE_START_R + i) * 4, copiedData[i + (int)DST_WRITE_OFFSET].A); } srcTex.Dispose(); dstTex.Dispose(); }); }
public void TestCopyTo() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants const uint MIP0_WIDTH = 512U; const uint ARRAY_LENGTH = 10U; Texture1DArray <TexelFormat.RGBA32UInt> srcArray = TextureFactory.NewTexture1D <TexelFormat.RGBA32UInt>() .WithDynamicDetail(false) .WithInitialData( Enumerable.Repeat( Enumerable.Range(0, (int)TextureUtils.GetSizeTexels(true, MIP0_WIDTH)) .Select(i => (uint)i) .Select(i => new TexelFormat.RGBA32UInt { R = i, G = i * 2, B = i * 3, A = i * 4 }), (int)ARRAY_LENGTH ) .Flatten() .ToArray() ) .WithMipAllocation(true) .WithMipGenerationTarget(false) .WithPermittedBindings(GPUBindings.ReadableShaderResource) .WithUsage(ResourceUsage.Immutable) .WithMipAllocation(true) .WithUsage(ResourceUsage.Write) .WithWidth(MIP0_WIDTH) .CreateArray(ARRAY_LENGTH); // Set up context Texture1DArray <TexelFormat.RGBA32UInt> dstArray = srcArray.Clone() .WithUsage(ResourceUsage.StagingRead) .WithPermittedBindings(GPUBindings.None) .CreateArray(srcArray.ArrayLength); srcArray.CopyTo(dstArray); var data = dstArray[4].ReadAll(); // Execute for (int i = 0, curMipIndex = 0; i < data.Length; ++curMipIndex) { for (int j = 0; j < dstArray.MipWidth((uint)curMipIndex); ++j, ++i) { Assert.AreEqual((uint)i, data[i].R); Assert.AreEqual((uint)i * 2, data[i].G); Assert.AreEqual((uint)i * 3, data[i].B); Assert.AreEqual((uint)i * 4, data[i].A); } } // Assert outcome srcArray.Dispose(); dstArray.Dispose(); }); }
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; })); }
public void TestDiscardWrite() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants const uint WIDTH_TX = 400U; const uint HEIGHT_TX = 200U; const uint WRITE_OFFSET_U = 190U; const uint WRITE_OFFSET_V = 10U; const int NUM_TX_TO_WRITE = 13555; Texture2D <TexelFormat.RGB32UInt> srcTex = TextureFactory.NewTexture2D <TexelFormat.RGB32UInt>() .WithPermittedBindings(GPUBindings.ReadableShaderResource) .WithUsage(ResourceUsage.DiscardWrite) .WithWidth(WIDTH_TX) .WithHeight(HEIGHT_TX); // Set up context // Execute srcTex.DiscardWrite( Enumerable.Range(0, NUM_TX_TO_WRITE) .Select(i => new TexelFormat.RGB32UInt { R = (uint)i, G = (uint)i * 2, B = (uint)i * 3 }) .ToArray(), 0U, WRITE_OFFSET_U, WRITE_OFFSET_V ); Texture2D <TexelFormat.RGB32UInt> dstTex = srcTex.Clone() .WithUsage(ResourceUsage.StagingRead) .WithPermittedBindings(GPUBindings.None); srcTex.CopyTo(dstTex); // Assert outcome TexelFormat.RGB32UInt[] copiedData = dstTex.Read(0U).Data; int offset = (int)(WRITE_OFFSET_V * WIDTH_TX + WRITE_OFFSET_U); for (int i = 0; i < NUM_TX_TO_WRITE; ++i) { Assert.AreEqual((uint)i, copiedData[i + offset].R); Assert.AreEqual((uint)i * 2U, copiedData[i + offset].G); Assert.AreEqual((uint)i * 3U, copiedData[i + offset].B); } srcTex.Dispose(); dstTex.Dispose(); }); }
public void TestWrite() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants const uint WIDTH_TX = 512U; const uint TARGET_MIP_INDEX = 1U; const uint WRITE_OFFSET = 30U; const int NUM_TX_TO_WRITE = 198; Texture1D <TexelFormat.RGBA32Int> srcTex = TextureFactory.NewTexture1D <TexelFormat.RGBA32Int>() .WithPermittedBindings(GPUBindings.ReadableShaderResource) .WithMipAllocation(true) .WithDynamicDetail(true) .WithUsage(ResourceUsage.Write) .WithWidth(WIDTH_TX); // Set up context // Execute srcTex.Write( Enumerable.Range(0, NUM_TX_TO_WRITE) .Select(i => new TexelFormat.RGBA32Int { R = i, G = i * 2, B = i * 3, A = i * 4 }) .ToArray(), TARGET_MIP_INDEX, WRITE_OFFSET ); Texture1D <TexelFormat.RGBA32Int> dstTex = srcTex.Clone() .WithDynamicDetail(false) .WithUsage(ResourceUsage.StagingRead) .WithPermittedBindings(GPUBindings.None); srcTex.CopyTo(dstTex); // Assert outcome TexelArray1D <TexelFormat.RGBA32Int> copiedData = dstTex.Read(TARGET_MIP_INDEX); for (int i = 0; i < NUM_TX_TO_WRITE; ++i) { Assert.AreEqual(i, copiedData[i + (int)WRITE_OFFSET].R); Assert.AreEqual(i * 2, copiedData[i + (int)WRITE_OFFSET].G); Assert.AreEqual(i * 3, copiedData[i + (int)WRITE_OFFSET].B); Assert.AreEqual(i * 4, copiedData[i + (int)WRITE_OFFSET].A); } srcTex.Dispose(); dstTex.Dispose(); }); }
/// <summary> /// Performs a <see cref="ResourceUsage.StagingReadWrite"/> on this texture, allowing an in-place modification of the data /// through a read/write operation. This can be faster than an individual read and write operation in certain use cases. /// </summary> /// <param name="readWriteAction">An action that takes the supplied <see cref="RawResourceDataView3D{T}"/> and uses it to /// manipulate the data in-place. The supplied resource view is only valid for the duration of the invocation of this /// <see cref="Action"/>.</param> /// <param name="mipIndex">The mip index to read/write.</param> /// <exception cref="ResourceOperationUnavailableException">Thrown if <see cref="BaseResource.CanReadWrite"/> is /// <c>false</c>.</exception> public void ReadWrite(Action <RawResourceDataView3D <TTexel> > readWriteAction, uint mipIndex) { Assure.LessThan( mipIndex, NumMips, "Can not read from mip level " + mipIndex + ": Only " + NumMips + " present in texture." ); ThrowIfCannotReadWrite(); LosgapSystem.InvokeOnMaster(() => { lock (InstanceMutationLock) { if (IsDisposed) { Logger.Warn("Attempted read-write manipulation on disposed resource of type: " + GetType().Name); return; } IntPtr outDataPtr; uint outRowStrideBytes, outSliceStrideBytes; InteropUtils.CallNative( NativeMethods.ResourceFactory_MapSubresource, RenderingModule.DeviceContext, ResourceHandle, GetSubresourceIndex(mipIndex), ResourceMapping.ReadWrite, (IntPtr)(&outDataPtr), (IntPtr)(&outRowStrideBytes), (IntPtr)(&outSliceStrideBytes) ).ThrowOnFailure(); try { readWriteAction(new RawResourceDataView3D <TTexel>( outDataPtr, TexelSizeBytes, MipWidth(mipIndex), MipHeight(mipIndex), MipDepth(mipIndex), outRowStrideBytes, outSliceStrideBytes )); } finally { InteropUtils.CallNative( NativeMethods.ResourceFactory_UnmapSubresource, RenderingModule.DeviceContext, ResourceHandle, GetSubresourceIndex(mipIndex) ).ThrowOnFailure(); } } }); }
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 override unsafe void Flush() { IntPtr commandListHandleMem = RenderCommandTempMemPool.GetLocalPool().Reserve((uint)IntPtr.Size); QueueCommand(new RenderCommand(RenderCommandInstruction.FinishCommandList, (IntPtr)(&commandListHandleMem))); uint offset = 0U; bool success; for (int i = 0; i < DeferredActions.Count; i++) { KeyValuePair <uint, Action> curAction = DeferredActions[i]; char *failReason = stackalloc char[InteropUtils.MAX_INTEROP_FAIL_REASON_STRING_LENGTH + 1]; success = NativeMethods.RenderPassManager_FlushInstructions( (IntPtr)failReason, RenderingModule.DeviceContext, RenderCommandList.AlignedPointer + (int)offset * sizeof(RenderCommand), curAction.Key - offset ); if (!success) { throw new NativeOperationFailedException(Marshal.PtrToStringUni((IntPtr)failReason)); } offset = curAction.Key; curAction.Value(); } char *failReason2 = stackalloc char[InteropUtils.MAX_INTEROP_FAIL_REASON_STRING_LENGTH + 1]; success = NativeMethods.RenderPassManager_FlushInstructions( (IntPtr)failReason2, RenderingModule.DeviceContext, RenderCommandList.AlignedPointer + (int)offset * sizeof(RenderCommand), CurListIndex - offset ); if (!success) { throw new NativeOperationFailedException(Marshal.PtrToStringUni((IntPtr)failReason2)); } lastCommandListHandle = commandListHandleMem; LosgapSystem.InvokeOnMaster(invokeOnMasterAction); CurListIndex = 0U; DeferredActions.Clear(); RenderCommandTempMemPool.GetLocalPool().FreeAll(); }
/// <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)); }
internal unsafe static Vector3 GetBodyAngularVelocity(PhysicsBodyHandle body) { return(LosgapSystem.InvokeOnMaster(() => { AlignedAllocation <Vector4> vec4Aligned = new AlignedAllocation <Vector4>(16L, (uint)sizeof(Vector4)); InteropUtils.CallNative(NativeMethods.PhysicsManager_GetBodyAngularVelocity, body, vec4Aligned.AlignedPointer ).ThrowOnFailure(); try { return (Vector3)(*((Vector4 *)vec4Aligned.AlignedPointer)); } finally { vec4Aligned.Dispose(); } })); }
public static unsafe PhysicsShapeHandle CreateSimpleSphereShape(float radius, CollisionShapeOptionsDesc shapeOptions) { return(LosgapSystem.InvokeOnMaster(() => { AlignedAllocation <CollisionShapeOptionsDesc> shapeOptionsAligned = new AlignedAllocation <CollisionShapeOptionsDesc>(16L, (uint)sizeof(CollisionShapeOptionsDesc)); *((CollisionShapeOptionsDesc *)shapeOptionsAligned.AlignedPointer) = shapeOptions; PhysicsShapeHandle result; InteropUtils.CallNative( NativeMethods.PhysicsManager_CreateSimpleSphereShape, radius, shapeOptionsAligned.AlignedPointer, (IntPtr)(&result) ).ThrowOnFailure(); shapeOptionsAligned.Dispose(); return result; })); }
/// <summary> /// In fullscreen mode, this function sets the resolution of the display. In windowed mode, /// this function sets the size of the client area of the window. /// </summary> /// <param name="widthPx">The width, in pixels, of the new resolution.</param> /// <param name="heightPx">The height, in pixels, of the new resolution.</param> /// <seealso cref="SetResolution(Ophidian.Losgap.Rendering.NativeOutputResolution)"/> public void SetResolution(uint widthPx, uint heightPx) { LosgapSystem.InvokeOnMaster(() => { lock (WindowMutationLock) { if (IsClosed) { return; } InteropUtils.CallNative( NativeMethods.WindowFactory_SetResolution, WindowHandle, widthPx, heightPx ).ThrowOnFailure(); } }); }
public static unsafe PhysicsShapeHandle CreateBoxShape(float width, float height, float depth, CollisionShapeOptionsDesc shapeOptions) { return(LosgapSystem.InvokeOnMaster(() => { AlignedAllocation <CollisionShapeOptionsDesc> shapeOptionsAligned = new AlignedAllocation <CollisionShapeOptionsDesc>(16L, (uint)sizeof(CollisionShapeOptionsDesc)); *((CollisionShapeOptionsDesc *)shapeOptionsAligned.AlignedPointer) = shapeOptions; AlignedAllocation <Vector4> boxExtents = new AlignedAllocation <Vector4>(16L, (uint)sizeof(Vector4)); *((Vector4 *)boxExtents.AlignedPointer) = new Vector4(width * 0.5f, height * 0.5f, depth * 0.5f, 0f); PhysicsShapeHandle result; InteropUtils.CallNative( NativeMethods.PhysicsManager_CreateBoxShape, boxExtents.AlignedPointer, shapeOptionsAligned.AlignedPointer, (IntPtr)(&result) ).ThrowOnFailure(); shapeOptionsAligned.Dispose(); boxExtents.Dispose(); return result; })); }
public void TestCopyTo() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants const uint WIDTH_TX = 512U; Texture1D <TexelFormat.RGBA32Int> srcTex = TextureFactory.NewTexture1D <TexelFormat.RGBA32Int>() .WithDynamicDetail(false) .WithInitialData( Enumerable.Range(0, (int)TextureUtils.GetSizeTexels(true, WIDTH_TX)) .Select(i => new TexelFormat.RGBA32Int { R = i, G = i * 2, B = i * 3, A = i * 4 }) .ToArray() ) .WithMipAllocation(true) .WithMipGenerationTarget(false) .WithPermittedBindings(GPUBindings.ReadableShaderResource) .WithUsage(ResourceUsage.Immutable) .WithWidth(WIDTH_TX); // Set up context // Execute Texture1D <TexelFormat.RGBA32Int> dstTex = srcTex.Clone() .WithUsage(ResourceUsage.StagingRead) .WithPermittedBindings(GPUBindings.None); srcTex.CopyTo(dstTex); // Assert outcome TexelFormat.RGBA32Int[] copiedData = dstTex.ReadAll(); for (int i = 0; i < copiedData.Length; ++i) { Assert.AreEqual(i, copiedData[i].R); Assert.AreEqual(i * 2, copiedData[i].G); Assert.AreEqual(i * 3, copiedData[i].B); Assert.AreEqual(i * 4, copiedData[i].A); } srcTex.Dispose(); dstTex.Dispose(); }); }
public static unsafe PhysicsShapeHandle CreateConeShape(float radius, float height, CollisionShapeOptionsDesc shapeOptions, out Vector3 translationOffset) { //translationOffset = Vector3.DOWN * (height * 0.5f); translationOffset = Vector3.ZERO; return(LosgapSystem.InvokeOnMaster(() => { AlignedAllocation <CollisionShapeOptionsDesc> shapeOptionsAligned = new AlignedAllocation <CollisionShapeOptionsDesc>(16L, (uint)sizeof(CollisionShapeOptionsDesc)); *((CollisionShapeOptionsDesc *)shapeOptionsAligned.AlignedPointer) = shapeOptions; PhysicsShapeHandle result; InteropUtils.CallNative( NativeMethods.PhysicsManager_CreateConeShape, radius, height, shapeOptionsAligned.AlignedPointer, (IntPtr)(&result) ).ThrowOnFailure(); shapeOptionsAligned.Dispose(); return result; })); }
public void TestDiscardWrite() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants Buffer <decimal> testBuffer = BufferFactory.NewBuffer <decimal>() .WithUsage(ResourceUsage.DiscardWrite) .WithLength(300); Buffer <decimal> copyDestBuffer = testBuffer.Clone() .WithUsage(ResourceUsage.StagingRead) .WithPermittedBindings(GPUBindings.None); // Set up context // Execute testBuffer.DiscardWrite(Enumerable.Range(0, 300).Select(i => (decimal)i).ToArray(), 0); testBuffer.DiscardWrite(Enumerable.Range(0, 200).Select(i => (decimal)i).ToArray(), 100); testBuffer.DiscardWrite(new ArraySlice <decimal>(Enumerable.Range(0, 200).Select(i => (decimal)i).ToArray(), 50, 50), 24); #if !DEVELOPMENT && !RELEASE try { testBuffer.DiscardWrite(new ArraySlice <decimal>(Enumerable.Range(0, 200).Select(i => (decimal)i).ToArray(), 50), 250); Assert.Fail(); } catch (AssuranceFailedException) { } #endif testBuffer.CopyTo(copyDestBuffer); decimal[] testData = copyDestBuffer.Read(); for (int i = 24; i < 24 + 50; ++i) { Assert.AreEqual((decimal)(50 + (i - 24)), testData[i]); } // Assert outcome Assert.IsTrue(testBuffer.CanDiscardWrite); Assert.IsFalse(copyDestBuffer.CanDiscardWrite); testBuffer.Dispose(); copyDestBuffer.Dispose(); }); }
public void SetPhysicsShape( PhysicsShapeHandle shapeHandle, Vector3 physicsShapeOffset, float mass, bool forceIntransigence = false, bool disablePerformanceDeactivation = false, bool collideOnlyWithWorld = false, bool collideWithOnlyDynamics = false, float restitution = PhysicsManager.DEFAULT_RESTITUTION, float linearDamping = PhysicsManager.DEFAULT_LINEAR_DAMPING, float angularDamping = PhysicsManager.DEFAULT_ANGULAR_DAMPING, float friction = PhysicsManager.DEFAULT_FRICTION, float rollingFriction = PhysicsManager.DEFAULT_ROLLING_FRICTION) { LosgapSystem.InvokeOnMaster(() => { // Anti-deadlock measures x.x lock (InstanceMutationLock) { if (physicsBody != PhysicsBodyHandle.NULL) { physicsBody.Dispose(); } if (this.physicsShapeOffset == null) { this.physicsShapeOffset = new AlignedAllocation <Vector4>(TRANSFORM_ALIGNMENT, (uint)sizeof(Vector4)); } this.physicsShapeOffset.Value.Write(physicsShapeOffset); physicsBody = PhysicsManager.CreateRigidBody( shapeHandle, mass, disablePerformanceDeactivation, forceIntransigence, collideOnlyWithWorld, collideWithOnlyDynamics, transform.AlignedPointer + 32, transform.AlignedPointer + 16, this.physicsShapeOffset.Value.AlignedPointer ); } }); SetPhysicsProperties(restitution, linearDamping, angularDamping, friction, rollingFriction); }
internal unsafe static FixedConstraintHandle CreateFixedConstraint( PhysicsBodyHandle parentBody, PhysicsBodyHandle childBody, Vector3 parentInitialTranslation, Quaternion parentInitialRotation, Vector3 childInitialTranslation, Quaternion childInitialRotation) { return(LosgapSystem.InvokeOnMaster(() => { Vector3 parentInitTransLocal = parentInitialTranslation; Quaternion parentInitRotLocal = parentInitialRotation; Vector3 childInitTransLocal = childInitialTranslation; Quaternion childInitRotLocal = childInitialRotation; FixedConstraintHandle result; InteropUtils.CallNative(NativeMethods.PhysicsManager_CreateFixedConstraint, parentBody, childBody, (IntPtr)(&parentInitTransLocal), (IntPtr)(&parentInitRotLocal), (IntPtr)(&childInitTransLocal), (IntPtr)(&childInitRotLocal), (IntPtr)(&result) ); return result; })); }
public static unsafe PhysicsShapeHandle CreateCompoundCurveShape(IEnumerable <Vector3> vertices, CollisionShapeOptionsDesc shapeOptions) { return(LosgapSystem.InvokeOnMaster(() => { AlignedAllocation <CollisionShapeOptionsDesc> shapeOptionsAligned = new AlignedAllocation <CollisionShapeOptionsDesc>(16L, (uint)sizeof(CollisionShapeOptionsDesc)); *((CollisionShapeOptionsDesc *)shapeOptionsAligned.AlignedPointer) = shapeOptions; Vector3 *verticesLocal = stackalloc Vector3[vertices.Count()]; int numVertices = 0; foreach (Vector3 vertex in vertices) { verticesLocal[numVertices++] = vertex; } PhysicsShapeHandle result; InteropUtils.CallNative( NativeMethods.PhysicsManager_CreateCompoundCurveShape, (IntPtr)verticesLocal, (uint)numVertices / 8U, shapeOptionsAligned.AlignedPointer, (IntPtr)(&result) ).ThrowOnFailure(); shapeOptionsAligned.Dispose(); return result; })); }
internal static unsafe PhysicsBodyHandle RayTestNearest(Vector3 startPoint, Vector3 endPoint, out Vector3 hitPoint) { AlignedAllocation <Vector4> hitPointAligned = new AlignedAllocation <Vector4>(16L, (uint)sizeof(Vector4)); Vector4 *hitPoint4Ptr = (Vector4 *)hitPointAligned.AlignedPointer; var result = LosgapSystem.InvokeOnMaster(() => { AlignedAllocation <Vector4> startPointAligned = new AlignedAllocation <Vector4>(16L, (uint)sizeof(Vector4)); *((Vector4 *)startPointAligned.AlignedPointer) = startPoint; AlignedAllocation <Vector4> endPointAligned = new AlignedAllocation <Vector4>(16L, (uint)sizeof(Vector4)); *((Vector4 *)endPointAligned.AlignedPointer) = endPoint; Vector4 *hitPoint4PtrLocal = hitPoint4Ptr; PhysicsBodyHandle outPBH; InteropUtils.CallNative(NativeMethods.PhysicsManager_RayTestNearest, startPointAligned.AlignedPointer, endPointAligned.AlignedPointer, (IntPtr)(&outPBH), (IntPtr)(hitPoint4PtrLocal) ).ThrowOnFailure(); startPointAligned.Dispose(); endPointAligned.Dispose(); return(outPBH); }); try { if (result != PhysicsBodyHandle.NULL) { hitPoint = (Vector3)(*((Vector4 *)hitPointAligned.AlignedPointer)); } else { hitPoint = Vector3.ZERO; } return(result); } finally { hitPointAligned.Dispose(); } }
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(); }); }
/// <summary> /// Assists in performing a <see cref="ResourceUsage.StagingReadWrite"/> on this buffer by mapping it to CPU memory /// and providing a pointer to the data. /// </summary> /// <param name="mappedDataPtrAction">An action that usually will modify (read/write) the data at the given pointer. /// The supplied <see cref="IntPtr"/> is only valid for as long as the supplied /// <see cref="Action"/> is running.</param> protected void MapReadWrite(Action <IntPtr> mappedDataPtrAction) { ThrowIfCannotReadWrite(); LosgapSystem.InvokeOnMaster(() => Mutate_MapRead(mappedDataPtrAction, ResourceMapping.ReadWrite)); }