Exemple #1
0
        private void InitializeFromImpl(DataBox[] dataBoxes = null)
        {
            if (ParentTexture != null)
            {
                NativeDeviceChild = ParentTexture.NativeDeviceChild;
            }

            if (NativeDeviceChild == null)
            {
                switch (Dimension)
                {
                case TextureDimension.Texture1D:
                    NativeDeviceChild = new Texture1D(GraphicsDevice.NativeDevice, ConvertToNativeDescription1D(), ConvertDataBoxes(dataBoxes));
                    break;

                case TextureDimension.Texture2D:
                case TextureDimension.TextureCube:
                    NativeDeviceChild = new Texture2D(GraphicsDevice.NativeDevice, ConvertToNativeDescription2D(), ConvertDataBoxes(dataBoxes));
                    break;

                case TextureDimension.Texture3D:
                    NativeDeviceChild = new Texture3D(GraphicsDevice.NativeDevice, ConvertToNativeDescription3D(), ConvertDataBoxes(dataBoxes));
                    break;
                }

                GraphicsDevice.RegisterTextureMemoryUsage(SizeInBytes);
            }

            if (NativeShaderResourceView == null)
            {
                NativeShaderResourceView = GetShaderResourceView(ViewType, ArraySlice, MipLevel);
            }
            NativeUnorderedAccessView = GetUnorderedAccessView(ViewType, ArraySlice, MipLevel);
            NativeRenderTargetView    = GetRenderTargetView(ViewType, ArraySlice, MipLevel);
            NativeDepthStencilView    = GetDepthStencilView(out HasStencil);

            switch (textureDescription.Options)
            {
            case TextureOptions.None:
                SharedHandle = IntPtr.Zero;
                break;

            case TextureOptions.Shared:
                var sharedResource = NativeDeviceChild.QueryInterface <SharpDX.DXGI.Resource>();
                SharedHandle = sharedResource.SharedHandle;
                break;

#if STRIDE_GRAPHICS_API_DIRECT3D11
            case TextureOptions.SharedNthandle | TextureOptions.SharedKeyedmutex:
                var sharedResource1 = NativeDeviceChild.QueryInterface <SharpDX.DXGI.Resource1>();
                var uniqueName      = "Stride:" + Guid.NewGuid().ToString();
                SharedHandle       = sharedResource1.CreateSharedHandle(uniqueName, SharpDX.DXGI.SharedResourceFlags.Write);
                SharedNtHandleName = uniqueName;
                break;
#endif
            default:
                throw new ArgumentOutOfRangeException("textureDescription.Options");
            }
        }
Exemple #2
0
        protected internal override void OnDestroyed()
        {
            // If it was a View, do not release reference
            if (ParentTexture != null)
            {
                NativeDeviceChild = null;
            }
            else if (GraphicsDevice != null)
            {
                GraphicsDevice.RegisterTextureMemoryUsage(-SizeInBytes);
            }

            base.OnDestroyed();
        }
Exemple #3
0
        protected internal override void OnDestroyed()
        {
            // If it was a View, do not release reference
            if (ParentTexture != null)
            {
                NativeDeviceChild = null;
            }
            else if (GraphicsDevice != null)
            {
                GraphicsDevice.RegisterTextureMemoryUsage(-SizeInBytes);
            }

            ReleaseComObject(ref renderTargetView);
            ReleaseComObject(ref depthStencilView);

            base.OnDestroyed();
        }
Exemple #4
0
        private void OnRecreateImpl()
        {
            // Dependency: wait for underlying texture to be recreated
            if (ParentTexture != null && ParentTexture.LifetimeState != GraphicsResourceLifetimeState.Active)
            {
                return;
            }

            // Render Target / Depth Stencil are considered as "dynamic"
            if ((Usage == GraphicsResourceUsage.Immutable ||
                 Usage == GraphicsResourceUsage.Default) &&
                !IsRenderTarget && !IsDepthStencil)
            {
                return;
            }

            if (ParentTexture == null && GraphicsDevice != null)
            {
                GraphicsDevice.RegisterTextureMemoryUsage(-SizeInBytes);
            }

            InitializeFromImpl();
        }
        /// <inheritdoc/>
        protected internal override void OnDestroyed()
        {
            using (GraphicsDevice.UseOpenGLCreationContext())
            {
                if (TextureId != 0 && ParentTexture == null)
                {
                    if (IsRenderbuffer)
                    {
                        GL.DeleteRenderbuffers(1, ref TextureId);
                    }
                    else
                    {
                        GL.DeleteTextures(1, ref TextureId);
                    }

                    GraphicsDevice.RegisterTextureMemoryUsage(-SizeInBytes);
                }

                if (stencilId != 0)
                {
                    GL.DeleteRenderbuffers(1, ref stencilId);
                }

                if (pixelBufferObjectId != 0)
                {
                    GL.DeleteBuffers(1, ref pixelBufferObjectId);
                }
            }

            TextureTotalSize    = 0;
            TextureId           = 0;
            stencilId           = 0;
            pixelBufferObjectId = 0;

            base.OnDestroyed();
        }
Exemple #6
0
        private void InitializeFromImpl(DataBox[] dataBoxes = null)
        {
            bool hasInitData = dataBoxes != null && dataBoxes.Length > 0;

            if (ParentTexture != null)
            {
                ParentResource    = ParentTexture;
                NativeDeviceChild = ParentTexture.NativeDeviceChild;
            }

            if (NativeDeviceChild == null)
            {
                ClearValue?clearValue = GetClearValue();

                ResourceDescription nativeDescription;
                switch (Dimension)
                {
                case TextureDimension.Texture1D:
                    nativeDescription = ConvertToNativeDescription1D();
                    break;

                case TextureDimension.Texture2D:
                case TextureDimension.TextureCube:
                    nativeDescription = ConvertToNativeDescription2D();
                    break;

                case TextureDimension.Texture3D:
                    nativeDescription = ConvertToNativeDescription3D();
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                var initialResourceState = ResourceStates.GenericRead;

                var heapType             = HeapType.Default;
                var currentResourceState = initialResourceState;
                if (Usage == GraphicsResourceUsage.Staging)
                {
                    heapType            = HeapType.Readback;
                    NativeResourceState = ResourceStates.CopyDestination;
                    int totalSize = ComputeBufferTotalSize();
                    nativeDescription = ResourceDescription.Buffer(totalSize);

                    // Staging textures on DirectX 12 use buffer internally
                    NativeDeviceChild = GraphicsDevice.NativeDevice.CreateCommittedResource(new HeapProperties(heapType), HeapFlags.None, nativeDescription, NativeResourceState);

                    if (hasInitData)
                    {
                        var commandList = GraphicsDevice.NativeCopyCommandList;
                        commandList.Reset(GraphicsDevice.NativeCopyCommandAllocator, null);

                        Resource uploadResource;
                        int      uploadOffset;
                        var      uploadMemory = GraphicsDevice.AllocateUploadBuffer(totalSize, out uploadResource, out uploadOffset, TextureSubresourceAlignment);

                        // Copy data to the upload buffer
                        int dataBoxIndex         = 0;
                        var uploadMemoryMipStart = uploadMemory;
                        for (int arraySlice = 0; arraySlice < ArraySize; arraySlice++)
                        {
                            for (int mipLevel = 0; mipLevel < MipLevels; mipLevel++)
                            {
                                var databox     = dataBoxes[dataBoxIndex++];
                                var mipHeight   = CalculateMipSize(Width, mipLevel);
                                var mipRowPitch = ComputeRowPitch(mipLevel);

                                var uploadMemoryCurrent = uploadMemoryMipStart;
                                var dataPointerCurrent  = databox.DataPointer;
                                for (int rowIndex = 0; rowIndex < mipHeight; rowIndex++)
                                {
                                    Utilities.CopyMemory(uploadMemoryCurrent, dataPointerCurrent, mipRowPitch);
                                    uploadMemoryCurrent += mipRowPitch;
                                    dataPointerCurrent  += databox.RowPitch;
                                }

                                uploadMemoryMipStart += ComputeSubresourceSize(mipLevel);
                            }
                        }

                        // Copy from upload heap to actual resource
                        commandList.CopyBufferRegion(NativeResource, 0, uploadResource, uploadOffset, totalSize);

                        commandList.Close();

                        StagingFenceValue = 0;
                        GraphicsDevice.WaitCopyQueue();
                    }

                    return;
                }

                if (hasInitData)
                {
                    currentResourceState = ResourceStates.CopyDestination;
                }

                // TODO D3D12 move that to a global allocator in bigger committed resources
                NativeDeviceChild = GraphicsDevice.NativeDevice.CreateCommittedResource(new HeapProperties(heapType), HeapFlags.None, nativeDescription, currentResourceState, clearValue);
                GraphicsDevice.RegisterTextureMemoryUsage(SizeInBytes);

                if (hasInitData)
                {
                    // Trigger copy
                    var commandList = GraphicsDevice.NativeCopyCommandList;
                    commandList.Reset(GraphicsDevice.NativeCopyCommandAllocator, null);

                    long textureCopySize;
                    var  placedSubresources = new PlacedSubResourceFootprint[dataBoxes.Length];
                    var  rowCounts          = new int[dataBoxes.Length];
                    var  rowSizeInBytes     = new long[dataBoxes.Length];
                    GraphicsDevice.NativeDevice.GetCopyableFootprints(ref nativeDescription, 0, dataBoxes.Length, 0, placedSubresources, rowCounts, rowSizeInBytes, out textureCopySize);

                    SharpDX.Direct3D12.Resource uploadResource;
                    int uploadOffset;
                    var uploadMemory = GraphicsDevice.AllocateUploadBuffer((int)textureCopySize, out uploadResource, out uploadOffset, TextureSubresourceAlignment);

                    for (int i = 0; i < dataBoxes.Length; ++i)
                    {
                        var databox     = dataBoxes[i];
                        var dataPointer = databox.DataPointer;

                        var rowCount     = rowCounts[i];
                        var sliceCount   = placedSubresources[i].Footprint.Depth;
                        var rowSize      = (int)rowSizeInBytes[i];
                        var destRowPitch = placedSubresources[i].Footprint.RowPitch;

                        // Memcpy data
                        for (int z = 0; z < sliceCount; ++z)
                        {
                            var uploadMemoryCurrent = uploadMemory + (int)placedSubresources[i].Offset + z * destRowPitch * rowCount;
                            var dataPointerCurrent  = dataPointer + z * databox.SlicePitch;
                            for (int y = 0; y < rowCount; ++y)
                            {
                                Utilities.CopyMemory(uploadMemoryCurrent, dataPointerCurrent, rowSize);
                                uploadMemoryCurrent += destRowPitch;
                                dataPointerCurrent  += databox.RowPitch;
                            }
                        }

                        // Adjust upload offset (circular dependency between GetCopyableFootprints and AllocateUploadBuffer)
                        placedSubresources[i].Offset += uploadOffset;

                        commandList.CopyTextureRegion(new TextureCopyLocation(NativeResource, i), 0, 0, 0, new TextureCopyLocation(uploadResource, placedSubresources[i]), null);
                    }

                    commandList.ResourceBarrierTransition(NativeResource, ResourceStates.CopyDestination, initialResourceState);
                    commandList.Close();

                    GraphicsDevice.WaitCopyQueue();
                }

                NativeResourceState = initialResourceState;
            }

            NativeShaderResourceView  = GetShaderResourceView(ViewType, ArraySlice, MipLevel);
            NativeRenderTargetView    = GetRenderTargetView(ViewType, ArraySlice, MipLevel);
            NativeDepthStencilView    = GetDepthStencilView(out HasStencil);
            NativeUnorderedAccessView = GetUnorderedAccessView(ViewType, ArraySlice, MipLevel);
        }
        private void InitializeFromImpl(DataBox[] dataBoxes = null)
        {
            if (ParentTexture != null)
            {
                CopyParentAttributes();
            }

            if (TextureId == 0)
            {
                TextureTarget = GetTextureTarget(Dimension);

                bool compressed;
                OpenGLConvertExtensions.ConvertPixelFormat(GraphicsDevice, ref textureDescription.Format, out TextureInternalFormat, out TextureFormat, out TextureType, out TexturePixelSize, out compressed);

                DepthPitch = Description.Width * Description.Height * TexturePixelSize;
                RowPitch   = Description.Width * TexturePixelSize;

                IsDepthBuffer = ((Description.Flags & TextureFlags.DepthStencil) != 0);
                if (IsDepthBuffer)
                {
                    HasStencil = InternalHasStencil(Format);
                }
                else
                {
                    HasStencil = false;
                }

                if ((Description.Flags & TextureFlagsCustomResourceId) != 0)
                {
                    return;
                }

                using (var openglContext = GraphicsDevice.UseOpenGLCreationContext())
                {
                    TextureTotalSize = ComputeBufferTotalSize();

                    if (Description.Usage == GraphicsResourceUsage.Staging)
                    {
                        InitializeStagingPixelBufferObject(dataBoxes);
                        return; // TODO: This return causes "GraphicsDevice.RegisterTextureMemoryUsage(SizeInBytes);" not to get entered. Is that okay?
                    }

                    // Depth textures are renderbuffers for now // TODO: PERFORMANCE: Why? I think we should change that so we can sample them directly.
                    // TODO: enable switch  // TODO: What does this comment even mean?

                    IsRenderbuffer = !Description.IsShaderResource;

                    // Force to renderbuffer if MSAA is on because we don't support MSAA textures ATM (and they don't exist on OpenGL ES).
                    if (Description.IsMultisample)
                    {
                        // TODO: Ideally the caller of this method should be aware of this "force to renderbuffer",
                        //       because the caller won't be able to bind it as a texture.
                        IsRenderbuffer = true;
                    }

                    if (IsRenderbuffer)
                    {
                        CreateRenderbuffer();
                        return; // TODO: This return causes "GraphicsDevice.RegisterTextureMemoryUsage(SizeInBytes);" not to get entered. Is that okay?
                    }

                    GL.GenTextures(1, out TextureId);
                    GL.BindTexture(TextureTarget, TextureId);
                    SetFilterMode();

                    if (Description.MipLevels == 0)
                    {
                        throw new NotImplementedException();
                    }

                    var setSize = TextureSetSize(TextureTarget);

                    for (var arrayIndex = 0; arrayIndex < Description.ArraySize; ++arrayIndex)
                    {
                        int offsetArray = arrayIndex * Description.MipLevels;

                        for (int mipLevel = 0; mipLevel < Description.MipLevels; ++mipLevel)
                        {
                            DataBox dataBox;
                            Int3    dimensions = new Int3(CalculateMipSize(Description.Width, mipLevel),
                                                          CalculateMipSize(Description.Height, mipLevel),
                                                          CalculateMipSize(Description.Depth, mipLevel));
                            if (dataBoxes != null && mipLevel < dataBoxes.Length)
                            {
                                if (setSize > 1 && !compressed && dataBoxes[mipLevel].RowPitch != dimensions.X * TexturePixelSize)
                                {
                                    throw new NotSupportedException("Can't upload texture with pitch in glTexImage2D/3D.");
                                }
                                // Might be possible, need to check API better.
                                dataBox = dataBoxes[offsetArray + mipLevel];
                            }
                            else
                            {
                                dataBox = new DataBox();
                            }

                            switch (TextureTarget)
                            {
                            case TextureTarget.Texture1D:
                                CreateTexture1D(compressed, dimensions.X, mipLevel, dataBox);
                                break;

                            case TextureTarget.Texture2D:
                            case TextureTarget.TextureCubeMap:
                                CreateTexture2D(compressed, dimensions.X, dimensions.Y, mipLevel, arrayIndex, dataBox);
                                break;

                            case TextureTarget.Texture3D:
                                CreateTexture3D(compressed, dimensions.X, dimensions.Y, dimensions.Z, mipLevel, dataBox);
                                break;

                            case TextureTarget.Texture2DArray:
                                CreateTexture2DArray(compressed, dimensions.X, dimensions.Y, mipLevel, arrayIndex, dataBox);
                                break;
                            }
                        }
                    }

                    GL.BindTexture(TextureTarget, 0);   // This unbinds the texture.
                    if (openglContext.CommandList != null)
                    {
                        // If we messed up with some states of a command list, mark dirty states
                        openglContext.CommandList.boundShaderResourceViews[openglContext.CommandList.activeTexture] = null;
                    }
                }

                GraphicsDevice.RegisterTextureMemoryUsage(SizeInBytes);
            }
        }