Ejemplo n.º 1
0
        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));
            }
        }
Ejemplo n.º 3
0
 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;
 }
Ejemplo n.º 4
0
        private static IntPtr AllocAndZeroTemp(uint numBytes)
        {
            IntPtr result = RenderCommandTempMemPool.GetLocalPool().Reserve(numBytes);

            UnsafeUtils.ZeroMem(result, numBytes);
            return(result);
        }
Ejemplo n.º 5
0
        /// <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();
                }
            }
        }
Ejemplo n.º 6
0
        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
        }
Ejemplo n.º 7
0
        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));
        }
Ejemplo n.º 9
0
 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;
 }
Ejemplo n.º 10
0
        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;
     }));
 }
Ejemplo n.º 13
0
        /// <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;
            }));
        }
Ejemplo n.º 14
0
        /// <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();
                }
            }
        }
Ejemplo n.º 15
0
        /// <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
                                     )
                                 );
 }
Ejemplo n.º 19
0
        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));
        }
Ejemplo n.º 21
0
        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;
        }
Ejemplo n.º 22
0
        /// <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));
        }
Ejemplo n.º 23
0
        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);
        }
Ejemplo n.º 24
0
        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));
                }
            }
        }
Ejemplo n.º 26
0
        /// <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));
        }
Ejemplo n.º 27
0
        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();
        }
Ejemplo n.º 28
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();
                }
            });
        }
Ejemplo n.º 29
0
        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
        }
Ejemplo n.º 30
0
        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));
        }