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!"); } }
/// <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.")); }
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); }
/// <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()); }
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); }
/// <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(); }
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); } }
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); }
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); }
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)); }
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)); }
/// <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()); }
/// <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()); }
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); } }
/// <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()); }
/// <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()); }
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()); }
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(); }
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()); }
/// <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()); }
/// <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(); }
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); } }
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); }
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); } }
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); }
/// <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()); }