Beispiel #1
0
        void InitGraphics()
        {
            // create the triangle
            Vector3[] triangleVertices = { new Vector3(0.0f, 0.1f, 0.3f), new Vector3(0.11f, -0.1f, 0.3f), new Vector3(-0.11f, -0.1f, 0.3f) };

            // set up buffer description
            D3D11_BUFFER_DESC bd;

            bd.ByteWidth           = (uint)(sizeof(Vector3) * triangleVertices.Length);
            bd.Usage               = D3D11_USAGE.D3D11_USAGE_DEFAULT;
            bd.BindFlags           = (uint)D3D11_BIND_FLAG.D3D11_BIND_VERTEX_BUFFER;
            bd.CPUAccessFlags      = 0;
            bd.MiscFlags           = 0;
            bd.StructureByteStride = 0;

            // define subresource data
            D3D11_SUBRESOURCE_DATA srd = new D3D11_SUBRESOURCE_DATA
            {
                pSysMem = triangleVertices.AsSpan().GetPointer()
            };

            // create the vertex buffer
            if (FAILED(m_d3dDevice.Get()->CreateBuffer(&bd, &srd, vertexBuffer.GetAddressOf())))
            {
                throw new Exception("Critical Error: Unable to create vertex buffer!");
            }
        }
Beispiel #2
0
        /// <summary>
        /// Gets the default <see cref="GraphicsDevice"/> instance.
        /// </summary>
        /// <returns>The default <see cref="GraphicsDevice"/> instance supporting <see cref="D3D_FEATURE_LEVEL_11_0"/> and <see cref="D3D_SHADER_MODEL_6_0"/>.</returns>
        /// <exception cref="NotSupportedException">Thrown when a default device is not available.</exception>
        public static unsafe GraphicsDevice GetDefaultDevice()
        {
            using ComPtr <ID3D12Device> d3D12Device = default;
            using ComPtr <IDXGIAdapter> dxgiAdapter = default;

            DXGI_ADAPTER_DESC1 dxgiDescription1;

            if (TryGetDefaultDevice(d3D12Device.GetAddressOf(), dxgiAdapter.GetAddressOf(), &dxgiDescription1) ||
                TryGetWarpDevice(d3D12Device.GetAddressOf(), dxgiAdapter.GetAddressOf(), &dxgiDescription1))
            {
                return(GetOrCreateDevice(d3D12Device.Get(), dxgiAdapter.Get(), &dxgiDescription1));
            }

            return(ThrowHelper.ThrowNotSupportedException <GraphicsDevice>("Failed to retrieve the default device."));
        }
Beispiel #3
0
        private DeviceResources GetDeviceResources()
        {
            if (_deviceResources != null && _deviceResources.IsDeviceRemoved)
            {
                // All references to the existing D3D device must be released before a new device
                // can be created.

                _deviceResources = null;
                _main.OnDeviceRemoved();

#if DEBUG
                ComPtr <IDXGIDebug1> dxgiDebug = default;
                Guid iid = IID_IDXGIDebug1;
                if (SUCCEEDED(DXGIGetDebugInterface1(0, &iid, (void **)dxgiDebug.GetAddressOf())))
                {
                    dxgiDebug.Ptr->ReportLiveObjects(new Guid(0xe48ae283, 0xda80, 0x490b, 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x8),
                                                     DXGI_DEBUG_RLO_FLAGS.DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_FLAGS.DXGI_DEBUG_RLO_IGNORE_INTERNAL);
                }
#endif
            }

            if (_deviceResources == null)
            {
                _deviceResources = new DeviceResources();
                _deviceResources.SetWindow(CoreWindow.GetForCurrentThread());
                _main.CreateRenderers(_deviceResources);
            }
            return(_deviceResources);
        }
Beispiel #4
0
    /// <summary>
    /// Creates an <see cref="ID2D1Bitmap"/> instance.
    /// </summary>
    /// <param name="d2D1DeviceContext">The input <see cref="ID2D1DeviceContext"/> instance to use to create the bitmap source.</param>
    /// <param name="width">The width of the bitmap to create.</param>
    /// <param name="height">The height of the bitmap to create.</param>
    /// <returns>A new <see cref="ID2D1Bitmap"/> instance.</returns>
    public static unsafe ComPtr <ID2D1Bitmap> CreateD2D1BitmapAndSetAsTarget(ID2D1DeviceContext *d2D1DeviceContext, uint width, uint height)
    {
        D2D_SIZE_U d2DSize;

        d2DSize.width  = width;
        d2DSize.height = height;

        D2D1_BITMAP_PROPERTIES1 d2DBitmapProperties1Target = default;

        d2DBitmapProperties1Target.pixelFormat.format    = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
        d2DBitmapProperties1Target.pixelFormat.alphaMode = D2D1_ALPHA_MODE.D2D1_ALPHA_MODE_PREMULTIPLIED;
        d2DBitmapProperties1Target.bitmapOptions         =
            D2D1_BITMAP_OPTIONS.D2D1_BITMAP_OPTIONS_TARGET |
            D2D1_BITMAP_OPTIONS.D2D1_BITMAP_OPTIONS_CANNOT_DRAW;

        using ComPtr <ID2D1Bitmap> d2D1Bitmap1Target = default;

        // Create a target D2D1 bitmap
        d2D1DeviceContext->CreateBitmap(
            size: d2DSize,
            sourceData: null,
            pitch: 0,
            bitmapProperties: &d2DBitmapProperties1Target,
            bitmap: (ID2D1Bitmap1 **)d2D1Bitmap1Target.GetAddressOf()).Assert();

        d2D1DeviceContext->SetTarget((ID2D1Image *)d2D1Bitmap1Target.Get());

        return(d2D1Bitmap1Target.Move());
    }
Beispiel #5
0
        protected override unsafe ID3D12RootSignature *CreateRootSignature()
        {
            using ComPtr <ID3D10Blob> signature = null;
            using ComPtr <ID3D10Blob> error     = null;

            var rootSignatureDesc = new RootSignatureDesc
            {
                Flags = RootSignatureFlags.RootSignatureFlagAllowInputAssemblerInputLayout
            };

            SilkMarshal.ThrowHResult
            (
                D3D12.SerializeRootSignature
                (
                    &rootSignatureDesc, D3DRootSignatureVersion.D3DRootSignatureVersion1, signature.GetAddressOf(),
                    error.GetAddressOf()
                )
            );

            ID3D12RootSignature *rootSignature;

            var iid = ID3D12RootSignature.Guid;

            SilkMarshal.ThrowHResult
            (
                D3DDevice->CreateRootSignature
                (
                    nodeMask: 0, signature.Get().GetBufferPointer(), signature.Get().GetBufferSize(), &iid,
                    (void **)&rootSignature
                )
            );

            return(rootSignature);
        }
Beispiel #6
0
    /// <summary>
    /// Saves a given image buffer to a target path.
    /// </summary>
    /// <param name="filename">The path to save the image to.</param>
    /// <param name="width">The image width.</param>
    /// <param name="height">The image height.</param>
    /// <param name="strideInBytes">The image stride in bytes.</param>
    /// <param name="buffer">The image pixel buffer.</param>
    public static unsafe void SaveBitmapToFile(string filename, uint width, uint height, uint strideInBytes, byte *buffer)
    {
        using ComPtr <IWICImagingFactory2> wicImagingFactory2 = default;

        // Create a Windows Imaging Component (WIC) factory
        Windows.CoCreateInstance(
            rclsid: (Guid *)Unsafe.AsPointer(ref Unsafe.AsRef(in CLSID.CLSID_WICImagingFactory2)),
            pUnkOuter: null,
            dwClsContext: (uint)CLSCTX.CLSCTX_INPROC_SERVER,
            riid: Windows.__uuidof <IWICImagingFactory2>(),
            ppv: (void **)wicImagingFactory2.GetAddressOf()).Assert();

        using ComPtr <IWICBitmapEncoder> wicBitmapEncoder = default;

        // Create the image encoder
        wicImagingFactory2.Get()->CreateEncoder(
            guidContainerFormat: (Guid *)Unsafe.AsPointer(ref Unsafe.AsRef(in GUID.GUID_ContainerFormatPng)),
            pguidVendor: null,
            ppIEncoder: wicBitmapEncoder.GetAddressOf()).Assert();

        using ComPtr <IWICStream> wicStream = default;

        // Create and initialize a stream to the target file
        wicImagingFactory2.Get()->CreateStream(wicStream.GetAddressOf()).Assert();

        fixed(char *p = filename)
        {
            // Initialize the stream to the target file
            wicStream.Get()->InitializeFromFilename((ushort *)p, Windows.GENERIC_WRITE);
        }

        // Initialize the encoder
        wicBitmapEncoder.Get()->Initialize(
            pIStream: (IStream *)wicStream.Get(),
            cacheOption: WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache).Assert();

        using ComPtr <IWICBitmapFrameEncode> wicBitmapFrameEncode = default;

        // Create the image frame and initialize it
        wicBitmapEncoder.Get()->CreateNewFrame(wicBitmapFrameEncode.GetAddressOf(), null).Assert();

        Guid wicTargetPixelFormatGuid = GUID.GUID_WICPixelFormat32bppPBGRA;

        // Set the encoding properties
        wicBitmapFrameEncode.Get()->Initialize(null).Assert();
        wicBitmapFrameEncode.Get()->SetSize(width, height).Assert();
        wicBitmapFrameEncode.Get()->SetPixelFormat(&wicTargetPixelFormatGuid).Assert();

        // Encode the target image
        wicBitmapFrameEncode.Get()->WritePixels(
            lineCount: height,
            cbStride: strideInBytes,
            cbBufferSize: strideInBytes * height,
            pbPixels: buffer).Assert();

        // Flush the changes
        wicBitmapFrameEncode.Get()->Commit();
        wicBitmapEncoder.Get()->Commit();
    }
Beispiel #7
0
        internal override bool TryGetAdapterByIndex(uint index, out Adapter adapter)
        {
            // We only set this to true in TryOrderByPreference which checks we have IDXGIFactory6 so we can hard cast _factory
            if (_enumByPreference)
            {
                while (true)
                {
                    using UniqueComPtr <IDXGIAdapter1> dxgiAdapter = default;


                    Guard.ThrowIfFailed(
                        _factory.Ptr->EnumAdapterByGpuPreference(
                            index + _skipAdapterOffset,
                            // DXGI preference doesn't allow preferring hardware/software adapters, so we do that manually after filtering out the other hardware types
                            // We remove the hardware and software flag so DXGI doesn't complain
                            (DXGI_GPU_PREFERENCE)(_preference & ~(DevicePreference.Hardware | DevicePreference.Software)),
                            dxgiAdapter.Iid,
                            (void **)&dxgiAdapter
                            )
                        );

                    // null adapter means we have reached end of list
                    if (!dxgiAdapter.Exists)
                    {
                        adapter = default;
                        return(false);
                    }

                    // if it only supports hardware of software, we have to filter them out. If both or neither are set, we allow all adapters through
                    if (_preference.HasFlag(DevicePreference.Hardware) != _preference.HasFlag(DevicePreference.Software))
                    {
                        DXGI_ADAPTER_DESC1 desc;
                        Guard.ThrowIfFailed(dxgiAdapter.Ptr->GetDesc1(&desc));
                        bool isHardware = (desc.Flags & (int)DXGI_ADAPTER_FLAG.DXGI_ADAPTER_FLAG_SOFTWARE) == 0;

                        // If they want hardware but we don't have it, or they want software and we don't have it, skip this adapter
                        if (_preference.HasFlag(DevicePreference.Hardware) != isHardware)
                        {
                            _skipAdapterOffset++;
                            continue;
                        }
                    }

                    adapter = CreateAdapter(dxgiAdapter.Move());

                    return(true);
                }
            }
            else
            {
                using UniqueComPtr <IDXGIAdapter1> dxgiAdapter = default;

                Guard.ThrowIfFailed(_factory.Ptr->EnumAdapters1(index, ComPtr.GetAddressOf(&dxgiAdapter)));
                adapter = CreateAdapter(dxgiAdapter.Move());

                return(true);
            }
        }
Beispiel #8
0
        protected override unsafe ID3D12RootSignature *CreateRootSignature()
        {
            using ComPtr <ID3DBlob> signature = null;
            using ComPtr <ID3DBlob> error     = null;

            var featureData = new D3D12_FEATURE_DATA_ROOT_SIGNATURE {
                // This is the highest version the sample supports. If CheckFeatureSupport succeeds, the HighestVersion returned will not be greater than this.
                HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1
            };

            if (FAILED(D3DDevice->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &featureData, (uint)sizeof(D3D12_FEATURE))))
            {
                featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;
            }

            const int RangesCount = 1;
            var       ranges      = stackalloc D3D12_DESCRIPTOR_RANGE1[RangesCount];

            ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC);

            const int RootParametersCount = 1;
            var       rootParameters      = stackalloc D3D12_ROOT_PARAMETER1[RootParametersCount];

            rootParameters[0].InitAsDescriptorTable(1, ranges, D3D12_SHADER_VISIBILITY_PIXEL);

            var sampler = new D3D12_STATIC_SAMPLER_DESC {
                Filter           = D3D12_FILTER.D3D12_FILTER_MIN_MAG_MIP_POINT,
                AddressU         = D3D12_TEXTURE_ADDRESS_MODE_BORDER,
                AddressV         = D3D12_TEXTURE_ADDRESS_MODE_BORDER,
                AddressW         = D3D12_TEXTURE_ADDRESS_MODE_BORDER,
                MipLODBias       = 0,
                MaxAnisotropy    = 0,
                ComparisonFunc   = D3D12_COMPARISON_FUNC_NEVER,
                BorderColor      = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK,
                MinLOD           = 0.0f,
                MaxLOD           = D3D12_FLOAT32_MAX,
                ShaderRegister   = 0,
                RegisterSpace    = 0,
                ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL,
            };

            var rootSignatureDesc = new D3D12_VERSIONED_ROOT_SIGNATURE_DESC();

            rootSignatureDesc.Init_1_1(RootParametersCount, rootParameters, 1, &sampler, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

            ThrowIfFailed(nameof(D3D12SerializeVersionedRootSignature), D3D12SerializeVersionedRootSignature(
                              &rootSignatureDesc, featureData.HighestVersion, signature.GetAddressOf(), error.GetAddressOf()));

            ID3D12RootSignature *rootSignature;

            var iid = IID_ID3D12RootSignature;

            ThrowIfFailed(nameof(ID3D12Device.CreateRootSignature), D3DDevice->CreateRootSignature(0, signature.Get()->GetBufferPointer(), signature.Get()->GetBufferSize(), &iid, (void **)&rootSignature));

            return(rootSignature);
        }
Beispiel #9
0
        private static ComPtr <IDxcBlob> ThrowHslsCompilationException(IDxcOperationResult *dxcOperationResult)
        {
            using ComPtr <IDxcBlobEncoding> dxcBlobEncodingError = default;

            dxcOperationResult->GetErrorBuffer(dxcBlobEncodingError.GetAddressOf()).Assert();

            string message = new((sbyte *)dxcBlobEncodingError.Get()->GetBufferPointer());

            throw new HlslCompilationException(message);
        }
Beispiel #10
0
        public Image Load(byte *buffer, uint size)
        {
            using ComPtr <IWICStream> stream = default;
            CheckAndThrow(_factory.Get()->CreateStream(stream.GetAddressOf()), nameof(IWICImagingFactory.CreateStream));
            CheckAndThrow(stream.Get()->InitializeFromMemory(buffer, size), nameof(IWICStream.InitializeFromMemory));

            using ComPtr <IWICBitmapDecoder> decoder = default;
            CheckAndThrow(_factory.Get()->CreateDecoderFromStream((IStream *)stream.Get(), null, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf()), nameof(IWICImagingFactory.CreateDecoderFromStream));
            return(LoadInternal(decoder));
        }
Beispiel #11
0
        public ComPtr <IDxcBlob> CompileShader(ReadOnlySpan <char> source)
        {
            using ComPtr <IDxcBlobEncoding> dxcBlobEncoding       = default;
            using ComPtr <IDxcOperationResult> dxcOperationResult = default;
            using ComPtr <IDxcBlob> dxcBlobBytecode = default;

            // Get the encoded blob from the source code
            fixed(char *p = source)
            {
                DxcLibrary.Get()->CreateBlobWithEncodingOnHeapCopy(
                    p,
                    (uint)source.Length * 2,
                    1200,
                    dxcBlobEncoding.GetAddressOf()).Assert();
            }

            // Try to compile the new compute shader
            fixed(char *shaderName = "")
            fixed(char *entryPoint       = nameof(IComputeShader.Execute))
            fixed(char *shaderProfile    = "cs_6_0")
            fixed(char *optimization     = "-O3")
            fixed(char *rowMajor         = "-Zpr")
            fixed(char *warningsAsErrors = "-Werror")
            {
                char **arguments = stackalloc char *[3] {
                    optimization, rowMajor, warningsAsErrors
                };

                DxcCompiler.Get()->Compile(
                    (IDxcBlob *)dxcBlobEncoding.Get(),
                    (ushort *)shaderName,
                    (ushort *)entryPoint,
                    (ushort *)shaderProfile,
                    (ushort **)arguments,
                    3,
                    null,
                    0,
                    DxcIncludeHandler.Get(),
                    dxcOperationResult.GetAddressOf()).Assert();
            }

            int status;

            dxcOperationResult.Get()->GetStatus(&status).Assert();

            // The compilation was successful, so we can extract the shader bytecode
            if (status == 0)
            {
                dxcOperationResult.Get()->GetResult(dxcBlobBytecode.GetAddressOf()).Assert();

                return(dxcBlobBytecode.Move());
            }

            return(ThrowHslsCompilationException(dxcOperationResult));
        }
Beispiel #12
0
    /// <summary>
    /// Creates an <see cref="ID2D1DeviceContext"/> instance.
    /// </summary>
    /// <param name="d2D1Device">The input <see cref="ID2D1Device"/> instance to use to create the context.</param>
    /// <returns>A new <see cref="ID2D1DeviceContext"/> instance.</returns>
    public static unsafe ComPtr <ID2D1DeviceContext> CreateD2D1DeviceContext(ID2D1Device *d2D1Device)
    {
        using ComPtr <ID2D1DeviceContext> d2D1DeviceContext = default;

        // Create a D2D1 device context
        d2D1Device->CreateDeviceContext(
            options: D2D1_DEVICE_CONTEXT_OPTIONS.D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
            deviceContext: d2D1DeviceContext.GetAddressOf()).Assert();

        return(d2D1DeviceContext.Move());
    }
Beispiel #13
0
    /// <summary>
    /// Creates an <see cref="ID2D1Bitmap"/> instance.
    /// </summary>
    /// <param name="d2D1DeviceContext">The input <see cref="ID2D1DeviceContext"/> instance to use to create the bitmap source.</param>
    /// <param name="wicBitmap">The input <see cref="IWICBitmap"/> to use to create the bitmap source.</param>
    /// <param name="d2D1Effect">The input <see cref="ID2D1Effect"/> to set the source for.</param>
    /// <returns>A new <see cref="ID2D1Bitmap"/> instance.</returns>
    public static unsafe ComPtr <ID2D1Bitmap> CreateD2D1BitmapAndSetAsSource(ID2D1DeviceContext *d2D1DeviceContext, IWICBitmap *wicBitmap, ID2D1Effect *d2D1Effect)
    {
        using ComPtr <ID2D1Bitmap> d2D1BitmapSource = default;

        // Create a source D2D1 bitmap from the WIC bitmap
        d2D1DeviceContext->CreateBitmapFromWicBitmap(
            wicBitmapSource: (IWICBitmapSource *)wicBitmap,
            bitmap: d2D1BitmapSource.GetAddressOf()).Assert();

        d2D1Effect->SetInput(0, (ID2D1Image *)d2D1BitmapSource.Get());

        return(d2D1BitmapSource.Move());
    }
Beispiel #14
0
        bool TryCompilePixelShader(string shaderName, out ComPtr <ID3DBlob> shaderBlob, out ComPtr <ID3D11PixelShader> pixelShader)
        {
            try
            {
                shaderBlob = new ComPtr <ID3DBlob>();
                ID3DBlob *errorBlob;
                uint      flags = D3DCOMPILE_ENABLE_STRICTNESS;
#if DEBUG
                flags |= D3DCOMPILE_DEBUG;
#endif
                // Prefer higher CS shader profile when possible as CS 5.0 provides better performance on 11-class hardware.
                var     profile         = (m_d3dDevice.Get()->GetFeatureLevel() >= D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_11_0) ? "ps_5_0" : "ps_4_0_level_9_1";
                HRESULT shaderCompileHr = D3DCompileFromFile(
                    GetShaderFilePath(shaderName).Select(c => (ushort)c).ToArray().AsSpan().AsPointer(),
                    null,
                    D3D_COMPILE_STANDARD_FILE_INCLUDE,
                    Encoding.ASCII.GetBytes(shaderName).Select(b => (sbyte)b).ToArray().AsSpan().AsPointer(),
                    profile.Select(c => (sbyte)c).ToArray().AsSpan().AsPointer(),
                    flags,
                    0,
                    shaderBlob.GetAddressOf(),
                    &errorBlob
                    );
                if (shaderCompileHr.FAILED)
                {
                    var errorStr = Marshal.PtrToStringAnsi(new IntPtr(errorBlob->GetBufferPointer()));
                    errorBlob->Release();
                    throw new Exception(errorStr);
                }

                pixelShader = new ComPtr <ID3D11PixelShader>();
                Marshal.ThrowExceptionForHR(
                    m_d3dDevice.Get()->CreatePixelShader(
                        shaderBlob.Get()->GetBufferPointer(),
                        shaderBlob.Get()->GetBufferSize(),
                        null,
                        pixelShader.GetAddressOf()
                        )
                    );

                return(true);
            }
            catch
            {
                shaderBlob  = null;
                pixelShader = null;
                return(false);
            }
        }
Beispiel #15
0
    /// <summary>
    /// Creates an <see cref="ID2D1Factory2"/> instance.
    /// </summary>
    /// <returns>A new <see cref="ID2D1Factory2"/> instance.</returns>
    public static unsafe ComPtr <ID2D1Factory2> CreateD2D1Factory2()
    {
        using ComPtr <ID2D1Factory2> d2D1Factory2 = default;

        D2D1_FACTORY_OPTIONS d2D1FactoryOptions = default;

        // Create a Direct2D factory
        DirectX.D2D1CreateFactory(
            factoryType: D2D1_FACTORY_TYPE.D2D1_FACTORY_TYPE_SINGLE_THREADED,
            riid: Windows.__uuidof <ID2D1Factory2>(),
            pFactoryOptions: &d2D1FactoryOptions,
            ppIFactory: (void **)d2D1Factory2.GetAddressOf()).Assert();

        return(d2D1Factory2.Move());
    }
    /// <summary>
    /// Creates a <see cref="D3D12MA_Pool"/> instance suited to be used for cache coherent UMA devices.
    /// </summary>
    /// <param name="allocator">The <see cref="D3D12MA_Allocator"/> instance in use.</param>
    /// <returns>A <see cref="D3D12MA_Pool"/> instance suited to be used for cache coherent UMA devices.</returns>
    public static ComPtr <D3D12MA_Pool> CreatePoolForCacheCoherentUMA(this ref D3D12MA_Allocator allocator)
    {
        using ComPtr <D3D12MA_Pool> pool = default;

        D3D12MA_POOL_DESC poolDesc = default;

        poolDesc.HeapProperties.CreationNodeMask     = 1;
        poolDesc.HeapProperties.VisibleNodeMask      = 1;
        poolDesc.HeapProperties.Type                 = D3D12_HEAP_TYPE_CUSTOM;
        poolDesc.HeapProperties.CPUPageProperty      = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
        poolDesc.HeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0;

        allocator.CreatePool(&poolDesc, pool.GetAddressOf()).Assert();

        return(pool.Move());
    }
Beispiel #17
0
    /// <summary>
    /// Creates an <see cref="ID2D1Device"/> instance.
    /// </summary>
    /// <param name="d2D1Factory2">The input <see cref="ID2D1Factory2"/> instance to use to create the device.</param>
    /// <returns>A new <see cref="ID2D1Device"/> instance.</returns>
    public static unsafe ComPtr <ID2D1Device> CreateD2D1Device(ID2D1Factory2 *d2D1Factory2)
    {
        using ComPtr <ID3D11Device> d3D11Device = default;

        uint creationFlags = (uint)D3D11_CREATE_DEVICE_FLAG.D3D11_CREATE_DEVICE_BGRA_SUPPORT;
        D3D_FEATURE_LEVEL *featureLevels = stackalloc[]
        {
            D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_11_1,
            D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_11_0,
            D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_10_1,
            D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_10_0,
            D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_9_3,
            D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_9_2,
            D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_9_1
        };
        D3D_FEATURE_LEVEL d3DFeatureLevel;

        // Create the Direct3D 11 API device and context
        DirectX.D3D11CreateDevice(
            pAdapter: null,
            DriverType: D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_HARDWARE,
            Software: HMODULE.NULL,
            Flags: creationFlags,
            pFeatureLevels: featureLevels,
            FeatureLevels: 7,
            SDKVersion: D3D11.D3D11_SDK_VERSION,
            ppDevice: d3D11Device.GetAddressOf(),
            pFeatureLevel: &d3DFeatureLevel,
            ppImmediateContext: null).Assert();

        using ComPtr <IDXGIDevice3> dxgiDevice3 = default;

        // Get a DXGI device from the D3D11 device
        d3D11Device.CopyTo(dxgiDevice3.GetAddressOf()).Assert();

        using ComPtr <ID2D1Device> d2D1Device = default;

        // Create a D2D1 device
        d2D1Factory2->CreateDevice(
            dxgiDevice: (IDXGIDevice *)dxgiDevice3.Get(),
            d2dDevice: d2D1Device.GetAddressOf());

        return(d2D1Device.Move());
    }
Beispiel #18
0
    private static ComPtr <IDxcBlob> ThrowHslsCompilationException(IDxcOperationResult *dxcOperationResult)
    {
        using ComPtr <IDxcBlobEncoding> dxcBlobEncodingError = default;

        dxcOperationResult->GetErrorBuffer(dxcBlobEncodingError.GetAddressOf()).Assert();

        string message = new((sbyte *)dxcBlobEncodingError.Get()->GetBufferPointer());

        // The error message will be in a format like this:
        // "hlsl.hlsl:11:20: error: redefinition of 'float1' as different kind of symbol
        //     static const float float1 = asfloat(0xFFC00000);
        //                        ^
        // note: previous definition is here"
        // These regex-s try to match the unnecessary headers and remove them, if present.
        // This doesn't need to be bulletproof, and these regex-s should match all cases anyway.
        message = Regex.Replace(message, @"^hlsl\.hlsl:\d+:\d+: (\w+:)", static m => m.Groups[1].Value, RegexOptions.Multiline);

        // Add a trailing '.' if not present
        if (message is { Length : > 0 } &&
    /// <summary>
    /// Applies the actual resize logic that was scheduled from <see cref="OnResize"/>.
    /// </summary>
    private unsafe void ApplyResize()
    {
        this.d3D12CommandQueue.Get()->Signal(this.d3D12Fence.Get(), this.nextD3D12FenceValue);

        // Wait for the fence again to ensure there are no pending operations
        this.d3D12Fence.Get()->SetEventOnCompletion(this.nextD3D12FenceValue, default);

        this.nextD3D12FenceValue++;

        // Dispose the old buffers before resizing the buffer
        this.d3D12Resource0.Dispose();
        this.d3D12Resource1.Dispose();

        // Resize the swap chain buffers
        this.dxgiSwapChain1.Get()->ResizeBuffers(0, 0, 0, DXGI_FORMAT.DXGI_FORMAT_UNKNOWN, 0);

        // Get the index of the initial back buffer
        using (ComPtr <IDXGISwapChain3> dxgiSwapChain3 = default)
        {
            _ = this.dxgiSwapChain1.CopyTo(dxgiSwapChain3.GetAddressOf());

            this.currentBufferIndex = dxgiSwapChain3.Get()->GetCurrentBackBufferIndex();
        }

        // Retrieve the back buffers for the swap chain
        fixed(ID3D12Resource **d3D12Resource0 = this.d3D12Resource0)
        fixed(ID3D12Resource **d3D12Resource1 = this.d3D12Resource1)
        {
            _ = dxgiSwapChain1.Get()->GetBuffer(0, Windows.__uuidof <ID3D12Resource>(), (void **)d3D12Resource0);
            _ = dxgiSwapChain1.Get()->GetBuffer(1, Windows.__uuidof <ID3D12Resource>(), (void **)d3D12Resource1);
        }

        this.texture?.Dispose();

        D3D12_RESOURCE_DESC d3D12Resource0Description = this.d3D12Resource0.Get()->GetDesc();

        // Create the 2D texture to use to generate frames to display
        this.texture = GraphicsDevice.Default.AllocateReadWriteTexture2D <Rgba32, float4>(
            (int)d3D12Resource0Description.Width,
            (int)d3D12Resource0Description.Height);
    }
    /// <summary>
    /// Embeds the bytecode for an exported shader as private data into another shader bytecode.
    /// </summary>
    /// <param name="shaderBlob">The bytecode produced by <see cref="CompileD2DFullShader(ReadOnlySpan{char}, D2D1ShaderProfile)"/>.</param>
    /// <param name="exportBlob">The bytecode produced by <see cref="CompileD2DFunction(ReadOnlySpan{char}, D2D1ShaderProfile)"/>.</param>
    /// <returns>An <see cref="ID3DBlob"/> instance with the combined data of <paramref name="shaderBlob"/> and <paramref name="exportBlob"/>.</returns>
    private static ComPtr <ID3DBlob> EmbedD2DFunctionPrivateData(ID3DBlob *shaderBlob, ID3DBlob *exportBlob)
    {
        void *shaderPtr  = shaderBlob->GetBufferPointer();
        nuint shaderSize = shaderBlob->GetBufferSize();

        void *exportPtr  = exportBlob->GetBufferPointer();
        nuint exportSize = exportBlob->GetBufferSize();

        using ComPtr <ID3DBlob> resultBlob = default;

        DirectX.D3DSetBlobPart(
            pSrcData: shaderPtr,
            SrcDataSize: shaderSize,
            Part: D3D_BLOB_PART.D3D_BLOB_PRIVATE_DATA,
            Flags: 0,
            pPart: exportPtr,
            PartSize: exportSize,
            ppNewShader: resultBlob.GetAddressOf()).Assert();

        return(resultBlob.Move());
    }
Beispiel #21
0
    private static void InitBackbuffer()
    {
        using ComPtr <ID3D11Resource> backbufferResource = default;
        fixed(Guid *resourcePointer = &D3D11Resource)
        {
            CheckAndThrow(_swapChain.Get()->GetBuffer(0, resourcePointer, (void **)backbufferResource.GetAddressOf()), nameof(IDXGISwapChain.GetBuffer));
        }

        ID3D11RenderTargetView *backbuffer;

        CheckAndThrow(_device.Get()->CreateRenderTargetView(backbufferResource.Get(), null, &backbuffer), nameof(ID3D11Device.CreateRenderTargetView));

        _backbufferHandle = TextureManager.CreateManual(new Texture
        {
            Format    = TextureFormats.RGBA32F,
            Width     = SwapChain.Width,
            Height    = SwapChain.Height,
            BindFlags = D3D11_BIND_FLAG.D3D11_BIND_RENDER_TARGET,
            D3DTarget = backbuffer,
            Usage     = D3D11_USAGE.D3D11_USAGE_IMMUTABLE
        });
    }
    /// <summary>
    /// Creates a new <see cref="ShaderCompiler"/> instance.
    /// </summary>
    private ShaderCompiler()
    {
        using ComPtr <IDxcCompiler> dxcCompiler             = default;
        using ComPtr <IDxcLibrary> dxcLibrary               = default;
        using ComPtr <IDxcIncludeHandler> dxcIncludeHandler = default;

        DirectX.DxcCreateInstance(
            (Guid *)Unsafe.AsPointer(ref Unsafe.AsRef(in CLSID.CLSID_DxcCompiler)),
            Windows.__uuidof <IDxcCompiler>(),
            dxcCompiler.GetVoidAddressOf()).Assert();

        DirectX.DxcCreateInstance(
            (Guid *)Unsafe.AsPointer(ref Unsafe.AsRef(in CLSID.CLSID_DxcLibrary)),
            Windows.__uuidof <IDxcLibrary>(),
            dxcLibrary.GetVoidAddressOf()).Assert();

        dxcLibrary.Get()->CreateIncludeHandler(dxcIncludeHandler.GetAddressOf()).Assert();

        DxcCompiler       = dxcCompiler.Move();
        DxcLibrary        = dxcLibrary.Move();
        DxcIncludeHandler = dxcIncludeHandler.Move();
    }
Beispiel #23
0
        void InitPipeline()
        {
            TryCompileVertexShader("SimpleVertexShader", out var vertexShaderBlob, out var vertexShader);
            TryCompilePixelShader("SimplePixelShader", out var pixelShaderBlob, out var pixelShader);

            // Set the shader objects as the active shaders
            m_d3dContext.Get()->VSSetShader(vertexShader, null, 0);
            m_d3dContext.Get()->PSSetShader(pixelShader, null, 0);

            // Create an input layout that matches the layout defined in the vertex shader code.
            D3D11_INPUT_ELEMENT_DESC[] basicVertexLayoutDesc =
            {
                new D3D11_INPUT_ELEMENT_DESC
                {
                    SemanticName         = "POSITION".GetAsciiSpan().AsPointer(),
                    SemanticIndex        = 0,
                    Format               = DXGI_FORMAT.DXGI_FORMAT_R32G32_FLOAT,
                    InputSlot            = 0,
                    AlignedByteOffset    = 0,
                    InputSlotClass       = D3D11_INPUT_CLASSIFICATION.D3D11_INPUT_PER_VERTEX_DATA,
                    InstanceDataStepRate = 0
                },
            };

            var inputLayout = new ComPtr <ID3D11InputLayout>();

            Marshal.ThrowExceptionForHR(
                m_d3dDevice.Get()->CreateInputLayout(
                    basicVertexLayoutDesc.AsSpan().AsPointer(),
                    (uint)basicVertexLayoutDesc.Length,
                    vertexShaderBlob.Get()->GetBufferPointer(),
                    vertexShaderBlob.Get()->GetBufferSize(),
                    inputLayout.GetAddressOf()
                    )
                );

            // set active input layout
            m_d3dContext.Get()->IASetInputLayout(inputLayout.Get());
        }
Beispiel #24
0
    /// <summary>
    /// Creates an <see cref="ID2D1Bitmap1"/> instance and copies data from a source bitmap.
    /// </summary>
    /// <param name="d2D1DeviceContext">The input <see cref="ID2D1DeviceContext"/> instance to use to create the bitmap.</param>
    /// <param name="d2D1Bitmap">The input <see cref="ID2D1Bitmap1"/> to read data from.</param>
    /// <param name="d2D1MappedRect">The resulting <see cref="D2D1_MAPPED_RECT"/> for the bitmap.</param>
    /// <returns>A new <see cref="ID2D1Bitmap1"/> instance.</returns>
    public static unsafe ComPtr <ID2D1Bitmap1> CreateD2D1Bitmap1Buffer(ID2D1DeviceContext *d2D1DeviceContext, ID2D1Bitmap *d2D1Bitmap, out D2D1_MAPPED_RECT d2D1MappedRect)
    {
        D2D_SIZE_U d2DSize = d2D1Bitmap->GetPixelSize();

        D2D1_BITMAP_PROPERTIES1 d2DBitmapProperties1Buffer = default;

        d2DBitmapProperties1Buffer.pixelFormat.format    = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
        d2DBitmapProperties1Buffer.pixelFormat.alphaMode = D2D1_ALPHA_MODE.D2D1_ALPHA_MODE_PREMULTIPLIED;
        d2DBitmapProperties1Buffer.bitmapOptions         = D2D1_BITMAP_OPTIONS.D2D1_BITMAP_OPTIONS_CPU_READ | D2D1_BITMAP_OPTIONS.D2D1_BITMAP_OPTIONS_CANNOT_DRAW;

        using ComPtr <ID2D1Bitmap1> d2D1Bitmap1Buffer = default;

        // Create a buffer D2D1 bitmap
        d2D1DeviceContext->CreateBitmap(
            size: d2DSize,
            sourceData: null,
            pitch: 0,
            bitmapProperties: &d2DBitmapProperties1Buffer,
            bitmap: d2D1Bitmap1Buffer.GetAddressOf()).Assert();

        D2D_POINT_2U d2DPointDestination = default;
        D2D_RECT_U   d2DRectSource       = new(0, 0, d2DSize.width, d2DSize.height);

        // Copy the image from the target to the readback bitmap
        d2D1Bitmap1Buffer.Get()->CopyFromBitmap(
            destPoint: &d2DPointDestination,
            bitmap: d2D1Bitmap,
            srcRect: &d2DRectSource);

        fixed(D2D1_MAPPED_RECT *d2D1MappedRectPtr = &d2D1MappedRect)
        {
            // Map the buffer bitmap
            d2D1Bitmap1Buffer.Get()->Map(
                options: D2D1_MAP_OPTIONS.D2D1_MAP_OPTIONS_READ,
                mappedRect: d2D1MappedRectPtr).Assert();
        }

        return(d2D1Bitmap1Buffer.Move());
    }
Beispiel #25
0
        /// <summary>
        /// Creates a new <see cref="ShaderCompiler"/> instance.
        /// </summary>
        private ShaderCompiler()
        {
            lock (this)
            {
                InitializeDxcLibrariesLoading();
            }

            using ComPtr <IDxcCompiler> dxcCompiler             = default;
            using ComPtr <IDxcLibrary> dxcLibrary               = default;
            using ComPtr <IDxcIncludeHandler> dxcIncludeHandler = default;

            Guid dxcCompilerCLGuid = FX.CLSID_DxcCompiler;
            Guid dxcLibraryCLGuid  = FX.CLSID_DxcLibrary;

            FX.DxcCreateInstance(&dxcCompilerCLGuid, FX.__uuidof <IDxcCompiler>(), dxcCompiler.GetVoidAddressOf()).Assert();
            FX.DxcCreateInstance(&dxcLibraryCLGuid, FX.__uuidof <IDxcLibrary>(), dxcLibrary.GetVoidAddressOf()).Assert();

            dxcLibrary.Get()->CreateIncludeHandler(dxcIncludeHandler.GetAddressOf()).Assert();

            DxcCompiler       = dxcCompiler.Move();
            DxcLibrary        = dxcLibrary.Move();
            DxcIncludeHandler = dxcIncludeHandler.Move();
        }
Beispiel #26
0
    protected override void CreateAssets()
    {
        using ComPtr <ID3D12Resource> textureUploadHeap = null;

        _texture = CreateTexture();
        base.CreateAssets();

        ID3D12Resource *CreateTexture()
        {
            // Describe and create a Texture2D.
            var textureDesc = new D3D12_RESOURCE_DESC {
                MipLevels        = 1,
                Format           = DXGI_FORMAT_R8G8B8A8_UNORM,
                Width            = TextureWidth,
                Height           = TextureHeight,
                Flags            = D3D12_RESOURCE_FLAG_NONE,
                DepthOrArraySize = 1,
                SampleDesc       = new DXGI_SAMPLE_DESC {
                    Count   = 1,
                    Quality = 0,
                },
                Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
            };

            ID3D12Resource *texture;
            var             iid = __uuidof <ID3D12Resource>();

            var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

            ThrowIfFailed(D3DDevice->CreateCommittedResource(
                              &heapProperties,
                              D3D12_HEAP_FLAG_NONE,
                              &textureDesc,
                              D3D12_RESOURCE_STATE_COPY_DEST,
                              pOptimizedClearValue: null,
                              iid,
                              (void **)&texture
                              ));

            var uploadBufferSize = GetRequiredIntermediateSize(texture, 0, 1);

            // Create the GPU upload buffer.
            heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
            var bufferDesc = D3D12_RESOURCE_DESC.Buffer(uploadBufferSize);

            ThrowIfFailed(D3DDevice->CreateCommittedResource(
                              &heapProperties,
                              D3D12_HEAP_FLAG_NONE,
                              &bufferDesc,
                              D3D12_RESOURCE_STATE_GENERIC_READ,
                              pOptimizedClearValue: null,
                              iid,
                              (void **)textureUploadHeap.GetAddressOf()
                              ));

            // Copy data to the intermediate upload heap and then schedule a copy
            // from the upload heap to the Texture2D.
            var textureData = GenerateTextureData();
            var rowPitch    = TextureWidth * TexturePixelSize;
            var slicePitch  = rowPitch * TextureHeight;
            D3D12_SUBRESOURCE_DATA textureSubresourceData;

            fixed(byte *pTextureData = &textureData[0])
            {
                textureSubresourceData = new D3D12_SUBRESOURCE_DATA {
                    pData      = (void *)pTextureData,
                    RowPitch   = (nint)rowPitch,
                    SlicePitch = (nint)slicePitch,
                };
            }

            _ = UpdateSubresources(GraphicsCommandList, texture, textureUploadHeap, 0, 0, 1, &textureSubresourceData);
            var barrier = D3D12_RESOURCE_BARRIER.InitTransition(texture, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

            GraphicsCommandList->ResourceBarrier(1, &barrier);

            // Describe and create a SRV for the texture.
            var srvDesc = new D3D12_SHADER_RESOURCE_VIEW_DESC {
                Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
                Format        = textureDesc.Format,
                ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D,
            };

            srvDesc.Anonymous.Texture2D.MipLevels = 1;

            D3DDevice->CreateShaderResourceView(texture, &srvDesc, _srvHeap->GetCPUDescriptorHandleForHeapStart());

            return(texture);
        }

        byte[] GenerateTextureData()
        {
            const uint RowPitch    = TextureWidth * TexturePixelSize;
            const uint CellPitch   = RowPitch >> 3;      // The width of a cell in the checkboard texture.
            const uint CellHeight  = TextureWidth >> 3;  // The height of a cell in the checkerboard texture.
            const uint TextureSize = RowPitch * TextureHeight;

            var data = new byte[TextureSize];

            fixed(byte *pData = &data[0])
            {
                for (uint n = 0; n < TextureSize; n += TexturePixelSize)
                {
                    var x = n % RowPitch;
                    var y = n / RowPitch;
                    var i = x / CellPitch;
                    var j = y / CellHeight;

                    if (i % 2 == j % 2)
                    {
                        pData[n]     = 0x00;    // R
                        pData[n + 1] = 0x00;    // G
                        pData[n + 2] = 0x00;    // B
                        pData[n + 3] = 0xff;    // A
                    }
                    else
                    {
                        pData[n]     = 0xff;    // R
                        pData[n + 1] = 0xff;    // G
                        pData[n + 2] = 0xff;    // B
                        pData[n + 3] = 0xff;    // A
                    }
                }
            }

            return(data);
        }
    }
Beispiel #27
0
    protected override unsafe ID3D12PipelineState *CreatePipelineState()
    {
        using ComPtr <ID3DBlob> pixelShader  = null;
        using ComPtr <ID3DBlob> vertexShader = null;

        var compileFlags = 0u;

#if DEBUG
        // Enable better shader debugging with the graphics debugging tools.
        compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
        fixed(char *fileName = GetAssetFullPath(@"D3D12\Assets\Shaders\HelloTexture.hlsl"))
        {
            var entryPoint = 0x00006E69614D5356;    // VSMain
            var target     = 0x0000305F355F7376;    // vs_5_0

            ThrowIfFailed(D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, vertexShader.GetAddressOf(), ppErrorMsgs: null));

            entryPoint = 0x00006E69614D5350;        // PSMain
            target     = 0x0000305F355F7370;        // ps_5_0
            ThrowIfFailed(D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, pixelShader.GetAddressOf(), ppErrorMsgs: null));
        }

        // Define the vertex input layout.
        const int InputElementDescsCount = 2;

        var semanticName0 = stackalloc ulong[2] {
            0x4E4F495449534F50,     // POSITION
            0x0000000000000000,
        };

        var semanticName1 = stackalloc ulong[2] {
            0x44524F4F43584554,     // TEXCOORD
            0x0000000000000000,
        };

        var inputElementDescs = stackalloc D3D12_INPUT_ELEMENT_DESC[InputElementDescsCount] {
            new D3D12_INPUT_ELEMENT_DESC {
                SemanticName   = (sbyte *)semanticName0,
                Format         = DXGI_FORMAT_R32G32B32_FLOAT,
                InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
            },
            new D3D12_INPUT_ELEMENT_DESC {
                SemanticName      = (sbyte *)semanticName1,
                Format            = DXGI_FORMAT_R32G32_FLOAT,
                AlignedByteOffset = 12,
                InputSlotClass    = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
            },
        };

        // Describe and create the graphics pipeline state object (PSO).
        var psoDesc = new D3D12_GRAPHICS_PIPELINE_STATE_DESC {
            InputLayout = new D3D12_INPUT_LAYOUT_DESC {
                pInputElementDescs = inputElementDescs,
                NumElements        = InputElementDescsCount,
            },
            pRootSignature    = RootSignature,
            VS                = new D3D12_SHADER_BYTECODE(vertexShader),
            PS                = new D3D12_SHADER_BYTECODE(pixelShader),
            RasterizerState   = D3D12_RASTERIZER_DESC.DEFAULT,
            BlendState        = D3D12_BLEND_DESC.DEFAULT,
            DepthStencilState = new D3D12_DEPTH_STENCIL_DESC {
                DepthEnable   = FALSE,
                StencilEnable = FALSE,
            },
            SampleMask            = uint.MaxValue,
            PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
            NumRenderTargets      = 1,
            SampleDesc            = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
        };
        psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;

        ID3D12PipelineState *pipelineState;
        ThrowIfFailed(D3DDevice->CreateGraphicsPipelineState(&psoDesc, __uuidof <ID3D12PipelineState>(), (void **)&pipelineState));

        return(pipelineState);
    }
Beispiel #28
0
        protected override void CreateWindowSizeDependentResources()
        {
            // Wait until all previous GPU work is complete.
            WaitForGpu(moveToNextFrame: false);

            // Clear the previous window size specific content and update the tracked fence values.
            for (var i = 0u; i < FrameCount; i++)
            {
                _renderTargets[i] = null;
                _fenceValues[i]   = _fenceValues[FrameIndex];
            }

            if (_swapChain != null)
            {
                ThrowIfFailed(nameof(IDXGISwapChain3.ResizeBuffers), _swapChain->ResizeBuffers(FrameCount, (uint)Size.Width, (uint)Size.Height, BackBufferFormat, 0));
            }
            else
            {
                _swapChain = CreateSwapChain();
            }

            CreateResourceViews();

            _viewport = new D3D12_VIEWPORT {
                TopLeftX = 0,
                TopLeftY = 0,
                Width    = Size.Width,
                Height   = Size.Height,
                MinDepth = D3D12_MIN_DEPTH,
                MaxDepth = D3D12_MAX_DEPTH
            };

            _scissorRect = new RECT {
                left   = 0,
                top    = 0,
                right  = Size.Width,
                bottom = Size.Height
            };

            IDXGISwapChain3 *CreateSwapChain()
            {
                using ComPtr <IDXGISwapChain1> swapChain = null;

                var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1 {
                    BufferCount = FrameCount,
                    Width       = (uint)Size.Width,
                    Height      = (uint)Size.Height,
                    Format      = BackBufferFormat,
                    BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
                    SwapEffect  = DXGI_SWAP_EFFECT_FLIP_DISCARD,
                    SampleDesc  = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
                };

                ThrowIfFailed(nameof(IDXGIFactory4.CreateSwapChainForHwnd), DxgiFactory->CreateSwapChainForHwnd(
                                  (IUnknown *)_commandQueue, // Swap chain needs the queue so that it can force a flush on it.
                                  Hwnd,
                                  &swapChainDesc,
                                  pFullscreenDesc: null,
                                  pRestrictToOutput: null,
                                  swapChain.GetAddressOf()
                                  ));

                IDXGISwapChain3 *swapChain3;

                var iid = IID_IDXGISwapChain3;

                ThrowIfFailed(nameof(IDXGISwapChain1.QueryInterface), swapChain.Get()->QueryInterface(&iid, (void **)&swapChain3));

                return(swapChain3);
            }
        }
Beispiel #29
0
    public static HRESULT CreateRootSignature(ID3D12Device *device, [NativeTypeName("const D3D12_ROOT_SIGNATURE_DESC *")] D3D12_ROOT_SIGNATURE_DESC *rootSignatureDesc, ID3D12RootSignature **rootSignature)
    {
        using ComPtr <ID3DBlob> pSignature = new ComPtr <ID3DBlob>();
        using ComPtr <ID3DBlob> pError     = new ComPtr <ID3DBlob>();

        HRESULT hr = D3D12SerializeRootSignature(rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetAddressOf(), pError.GetAddressOf());

        if (SUCCEEDED(hr))
        {
            hr = device->CreateRootSignature(0, pSignature.Get()->GetBufferPointer(), pSignature.Get()->GetBufferSize(), __uuidof <ID3D12RootSignature>(), (void **)rootSignature);
        }

        return(hr);
    }
Beispiel #30
0
    /// <summary>
    /// Loads an <see cref="IWICBitmap"/> instance from a given path.
    /// </summary>
    /// <param name="filename">The path to load the image from.</param>
    /// <param name="width">The resulting image width.</param>
    /// <param name="height">The resulting image height.</param>
    /// <returns>The resulting <see cref="IWICBitmap"/> instance.</returns>
    public static unsafe ComPtr <IWICBitmap> LoadBitmapFromFile(string filename, out uint width, out uint height)
    {
        using ComPtr <IWICImagingFactory2> wicImagingFactory2 = default;

        // Create a Windows Imaging Component (WIC) factory
        Windows.CoCreateInstance(
            rclsid: (Guid *)Unsafe.AsPointer(ref Unsafe.AsRef(in CLSID.CLSID_WICImagingFactory2)),
            pUnkOuter: null,
            dwClsContext: (uint)CLSCTX.CLSCTX_INPROC_SERVER,
            riid: Windows.__uuidof <IWICImagingFactory2>(),
            ppv: (void **)wicImagingFactory2.GetAddressOf()).Assert();

        using ComPtr <IWICBitmapDecoder> wicBitmapDecoder = default;

        // Get the bitmap decoder for the target file
        fixed(char *p = filename)
        {
            wicImagingFactory2.Get()->CreateDecoderFromFilename(
                wzFilename: (ushort *)p,
                pguidVendor: null,
                dwDesiredAccess: Windows.GENERIC_READ,
                metadataOptions: WICDecodeOptions.WICDecodeMetadataCacheOnDemand,
                ppIDecoder: wicBitmapDecoder.GetAddressOf()).Assert();
        }

        using ComPtr <IWICBitmapFrameDecode> wicBitmapFrameDecode = default;

        // Get the first frame of the loaded image (if more are present, they will be ignored)
        wicBitmapDecoder.Get()->GetFrame(0, wicBitmapFrameDecode.GetAddressOf()).Assert();

        fixed(uint *widthPtr = &width)
        fixed(uint *heightPtr = &height)
        {
            // Extract the image size info
            wicBitmapFrameDecode.Get()->GetSize(widthPtr, heightPtr).Assert();
        }

        Guid wicTargetPixelFormatGuid = GUID.GUID_WICPixelFormat32bppPBGRA;
        Guid wicActualPixelFormatGuid;

        // Get the current and target pixel format info
        wicBitmapFrameDecode.Get()->GetPixelFormat(&wicActualPixelFormatGuid).Assert();

        using ComPtr <IWICBitmap> wicBitmap = default;

        // Create the target bitmap
        wicImagingFactory2.Get()->CreateBitmap(
            uiWidth: width,
            uiHeight: height,
            pixelFormat: &wicTargetPixelFormatGuid,
            option: WICBitmapCreateCacheOption.WICBitmapCacheOnLoad,
            ppIBitmap: wicBitmap.GetAddressOf()).Assert();

        WICRect wicRect;

        wicRect.X      = 0;
        wicRect.Y      = 0;
        wicRect.Width  = (int)width;
        wicRect.Height = (int)height;

        using (ComPtr <IWICBitmapLock> wicBitmapLock = default)
        {
            // Lock the bitmap
            wicBitmap.Get()->Lock(
                prcLock: &wicRect,
                flags: (uint)WICBitmapLockFlags.WICBitmapLockWrite,
                ppILock: wicBitmapLock.GetAddressOf()).Assert();

            uint wicBitmapStride;

            // Get the stride
            wicBitmapLock.Get()->GetStride(&wicBitmapStride).Assert();

            uint  wicBitmapSize;
            byte *wicBitmapPointer;

            // Get the bitmap size and pointer
            wicBitmapLock.Get()->GetDataPointer(&wicBitmapSize, &wicBitmapPointer).Assert();

            // Check if a pixel format conversion is needed
            if (wicTargetPixelFormatGuid == wicActualPixelFormatGuid)
            {
                // No conversion is needed, just copy the pixels directly
                wicBitmapFrameDecode.Get()->CopyPixels(
                    prc: &wicRect,
                    cbStride: wicBitmapStride,
                    cbBufferSize: wicBitmapSize,
                    pbBuffer: wicBitmapPointer).Assert();
            }
            else
            {
                using ComPtr <IWICFormatConverter> wicFormatConverter = default;

                // Create a format converter
                wicImagingFactory2.Get()->CreateFormatConverter(wicFormatConverter.GetAddressOf()).Assert();

                // Get a format converter to decode the pixel data
                wicFormatConverter.Get()->Initialize(
                    pISource: (IWICBitmapSource *)wicBitmapFrameDecode.Get(),
                    dstFormat: &wicTargetPixelFormatGuid,
                    dither: WICBitmapDitherType.WICBitmapDitherTypeNone,
                    pIPalette: null,
                    alphaThresholdPercent: 0,
                    paletteTranslate: WICBitmapPaletteType.WICBitmapPaletteTypeCustom).Assert();

                // Decode the pixel data into the upload buffer
                wicFormatConverter.Get()->CopyPixels(
                    prc: &wicRect,
                    cbStride: wicBitmapStride,
                    cbBufferSize: wicBitmapSize,
                    pbBuffer: wicBitmapPointer).Assert();
            }
        }

        return(wicBitmap.Move());
    }