Example #1
0
        private static Result CreateTextureFromDDS(
            Device d3dDevice,
            DeviceContext deviceContext,
            DDS_HEADER header,
            DDS_HEADER_DXT10?header10,
            IntPtr bitData,
            int bitsize,
            int maxsize,
            ResourceUsage usage,
            BindFlags bindFlags,
            CpuAccessFlags cpuAccessFlags,
            ResourceOptionFlags resourceOptionFlags,
            bool forceSRGB,
            out Resource texture, out ShaderResourceView textureView)
        {
            texture     = null;
            textureView = null;

            int width  = Convert.ToInt32(header.width);
            int height = Convert.ToInt32(header.height);
            int depth  = Convert.ToInt32(header.depth);

            ResourceDimension resourceDimension = ResourceDimension.Unknown;
            int arraySize = 1;

            DXGI.Format format    = DXGI.Format.Unknown;
            bool        isCubeMap = false;

            int mipCount = Convert.ToInt32(header.mipMapCount);

            if (0 == mipCount)
            {
                mipCount = 1;
            }

            if (header.IsDX10)
            {
                var d3d10ext = header10.Value;
                arraySize = Convert.ToInt32(d3d10ext.arraySize);
                if (arraySize == 0)
                {
                    return(Result.InvalidArg);
                }

                switch (d3d10ext.dxgiFormat)
                {
                case DXGI.Format.AI44:
                case DXGI.Format.IA44:
                case DXGI.Format.P8:
                case DXGI.Format.A8P8:
                    return(Result.InvalidArg);

                default:
                    if (d3d10ext.dxgiFormat.BitPerPixel() == 0)
                    {
                        return(Result.InvalidArg);
                    }
                    break;
                }

                format = d3d10ext.dxgiFormat;

                switch (d3d10ext.resourceDimension)
                {
                case ResourceDimension.Texture1D:
                    // D3DX writes 1D textures with a fixed Height of 1
                    if ((header.flags.HasFlag(DDS_Header.Height)) && height != 1)
                    {
                        return(Result.InvalidArg);
                    }
                    height = depth = 1;
                    break;

                case ResourceDimension.Texture2D:
                    if (d3d10ext.miscFlag.HasFlag(ResourceOptionFlags.TextureCube))
                    {
                        arraySize *= 6;
                        isCubeMap  = true;
                    }
                    depth = 1;
                    break;

                case ResourceDimension.Texture3D:
                    if (!(header.flags.HasFlag(DDS_Header.Volume)))
                    {
                        return(Result.InvalidArg);
                    }

                    if (arraySize > 1)
                    {
                        return(Result.InvalidArg);
                    }
                    break;

                default:
                    return(Result.InvalidArg);
                }
                resourceDimension = d3d10ext.resourceDimension;
            }
            else
            {
                format = header.ddsPixelFormat.Format;

                if (format == DXGI.Format.Unknown)
                {
                    return(Result.InvalidArg);
                }

                if (header.flags.HasFlag(DDS_Header.Volume))
                {
                    resourceDimension = ResourceDimension.Texture3D;
                }
                else
                {
                    if (header.Caps2.HasFlag(DDS_CubeMap.CubeMap))
                    {
                        // We require all six faces to be defined
                        if (header.Caps2.HasFlag(DDS_CubeMap.AllFaces))
                        {
                            return(Result.InvalidArg);
                        }

                        arraySize = 6;
                        isCubeMap = true;
                    }

                    depth             = 1;
                    resourceDimension = ResourceDimension.Texture2D;

                    // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture
                }

                if (format.BitPerPixel() == 0)
                {
                    return(Result.InvalidArg);
                }
            }

            // Bound sizes (for security purposes we don't trust DDS file metadata larger than the D3D 11.x hardware requirements)
            if (mipCount > SharpDX.Direct3D11.Resource.MaximumMipLevels)
            {
                return(Result.InvalidArg);
            }

            switch (resourceDimension)
            {
            case ResourceDimension.Texture1D:
                if (arraySize > Resource.MaximumTexture1DArraySize || width > Resource.MaximumTexture1DSize)
                {
                    return(Result.InvalidArg);
                }
                break;

            case ResourceDimension.Texture2D:
                if (isCubeMap)
                {
                    if (arraySize > Resource.MaximumTexture2DArraySize || width > Resource.MaximumTexture2DSize || height > Resource.MaximumTexture2DSize)
                    {
                        return(Result.InvalidArg);
                    }
                }
                break;

            case ResourceDimension.Texture3D:
                if (arraySize > 1 ||
                    width > Resource.MaximumTexture3DSize ||
                    height > Resource.MaximumTexture3DSize ||
                    depth > Resource.MaximumTexture3DSize)
                {
                    return(Result.InvalidArg);
                }
                break;
            }

            // auto generate mipmaps
            bool autoGen = false;

            ////
            ////

            if (autoGen)
            {
            }
            else
            {
                DataBox[] initData = new DataBox[mipCount * arraySize];

                if (FillInitData(width, height, depth, mipCount, arraySize, format, bitData, bitsize, maxsize, out int twidth, out int theight, out int tdepth, out int skipMip, initData) == Result.Ok)
                {
                    var result = CreateD3DResources(d3dDevice, resourceDimension, twidth, theight, tdepth, mipCount - skipMip, arraySize,
                                                    format, usage, bindFlags, cpuAccessFlags, resourceOptionFlags, forceSRGB, isCubeMap, initData, out texture, out textureView);

                    if (!result.Success && maxsize == 0 && (mipCount > 1))
                    {
                        // Retry with a maxsize determined by feature level

                        switch (d3dDevice.FeatureLevel)
                        {
                        case FeatureLevel.Level_9_1:
                        case FeatureLevel.Level_9_2:
                            if (isCubeMap)
                            {
                                maxsize = 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/;
                            }
                            else
                            {
                                maxsize = (resourceDimension == ResourceDimension.Texture3D)
                                        ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
                                        : 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
                            }
                            break;

                        case FeatureLevel.Level_9_3:
                            maxsize = (resourceDimension == ResourceDimension.Texture3D)
                                    ? 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
                                    : 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
                            break;

                        default:           // D3D_FEATURE_LEVEL_10_0 & D3D_FEATURE_LEVEL_10_1
                            maxsize = (resourceDimension == ResourceDimension.Texture3D)
                                    ? 2048 /*D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/
                                    : 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
                            break;
                        }

                        if (FillInitData(width, height, depth, mipCount, arraySize, format, bitData, bitsize, maxsize,
                                         out twidth, out theight, out tdepth, out skipMip, initData).Success)
                        {
                            var hr = CreateD3DResources(d3dDevice, resourceDimension, twidth, theight, tdepth, mipCount - skipMip, arraySize,
                                                        format, usage, bindFlags, cpuAccessFlags, resourceOptionFlags, forceSRGB,
                                                        isCubeMap, initData, out texture, out textureView);
                        }
                    }
                }
            }

            return(Result.False);
        }
Example #2
0
        private static void GetSurfaceInfo(int width, int height, DXGI.Format fmt, out int numBytes, out int rowBytes, out int numRows)
        {
            rowBytes = 0;
            numRows  = 0;
            numBytes = 0;

            bool bc     = false;
            bool packed = false;
            bool planar = false;
            int  bpe    = 0;

            switch (fmt)
            {
            case DXGI.Format.BC1_Typeless:
            case DXGI.Format.BC1_UNorm:
            case DXGI.Format.BC1_UNorm_SRgb:
            case DXGI.Format.BC4_Typeless:
            case DXGI.Format.BC4_UNorm:
            case DXGI.Format.BC4_SNorm:
                bc  = true;
                bpe = 8;
                break;

            case DXGI.Format.BC2_Typeless:
            case DXGI.Format.BC2_UNorm:
            case DXGI.Format.BC2_UNorm_SRgb:
            case DXGI.Format.BC3_Typeless:
            case DXGI.Format.BC3_UNorm:
            case DXGI.Format.BC3_UNorm_SRgb:
            case DXGI.Format.BC5_Typeless:
            case DXGI.Format.BC5_UNorm:
            case DXGI.Format.BC5_SNorm:
            case DXGI.Format.BC6H_Typeless:
            case DXGI.Format.BC6H_Uf16:
            case DXGI.Format.BC6H_Sf16:
            case DXGI.Format.BC7_Typeless:
            case DXGI.Format.BC7_UNorm:
            case DXGI.Format.BC7_UNorm_SRgb:
                bc  = true;
                bpe = 16;
                break;

            case DXGI.Format.R8G8_B8G8_UNorm:
            case DXGI.Format.G8R8_G8B8_UNorm:
            case DXGI.Format.YUY2:
                packed = true;
                bpe    = 4;
                break;

            case DXGI.Format.Y210:
            case DXGI.Format.Y216:
                packed = true;
                bpe    = 8;
                break;

            case DXGI.Format.NV12:
            case DXGI.Format.Opaque420:
                planar = true;
                bpe    = 2;
                break;

            case DXGI.Format.P010:
            case DXGI.Format.P016:
                planar = true;
                bpe    = 4;
                break;
            }

            if (bc)
            {
                int numBlocksWide = 0;
                if (width > 0)
                {
                    numBlocksWide = Math.Max(1, (width + 3) / 4);
                }
                int numBlocksHigh = 0;
                if (height > 0)
                {
                    numBlocksHigh = Math.Max(1, (height + 3) / 4);
                }
                rowBytes = numBlocksWide * bpe;
                numRows  = numBlocksHigh;
                numBytes = rowBytes * numBlocksHigh;
            }
            else if (packed)
            {
                rowBytes = ((width + 1) >> 1) * bpe;
                numRows  = height;
                numBytes = rowBytes * height;
            }
            else if (fmt == DXGI.Format.NV11)
            {
                rowBytes = ((width + 3) >> 2) * 4;
                numRows  = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
                numBytes = rowBytes * numRows;
            }
            else if (planar)
            {
                rowBytes = ((width + 1) >> 1) * bpe;
                numBytes = (rowBytes * height) + ((rowBytes * height + 1) >> 1);
                numRows  = height + ((height + 1) >> 1);
            }
            else
            {
                int bpp = fmt.BitPerPixel();
                rowBytes = (width * bpp + 7) / 8; // round up to nearest byte
                numRows  = height;
                numBytes = rowBytes * height;
            }
        }