直接合成,IDCompositionGaussianBlurEffect 抛出访问冲突异常
Direct Composition, IDCompositionGaussianBlurEffect Throwing Access Violation Exception
我正在做一个基于这篇文章使用直接合成的项目:
Windows with C++ : High-Performance Window Layering Using the Windows Composition Engine
我能够重新创建示例并且它正在运行。目前我正在尝试将 IDCompositionGaussianBlurEffect 应用到我的视觉 (variable: visual)
但编译器抛出访问冲突异常。有没有什么方法可以使用直接合成将模糊效果应用到我的视觉对象上。
异常:
Exception thrown at 0x6E695565 (dcomp.dll) in DirectComNoCom.exe: 0xC0000005: Access violation reading location 0x41200000.
在这一行抛出异常:
effect->SetStandardDeviation(10.0f);
完整代码如下:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <wrl.h>
using namespace Microsoft::WRL;
#include <dxgi1_3.h>
#include <d3d11_2.h>
#include <d2d1_2.h>
#include <d2d1_2helper.h>
#include <dcomp.h>
#pragma comment(lib, "dxgi")
#pragma comment(lib, "d3d11")
#pragma comment(lib, "d2d1")
#pragma comment(lib, "dcomp")
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
ComPtr<ID3D11Device> direct3dDevice;
ComPtr<IDXGIDevice> dxgiDevice;
ComPtr<IDXGIFactory2> dxFactory;
ComPtr<IDXGISwapChain1> swapChain;
ComPtr<ID2D1Factory2> d2Factory;
ComPtr<ID2D1Device1> d2Device;
ComPtr<IDCompositionTarget> target;
struct ComException
{
HRESULT result;
ComException(HRESULT const value) :
result(value)
{}
};
void HR(HRESULT const result)
{
if (S_OK != result)
{
throw ComException(result);
}
}
void CreateVisual(HWND hwnd)
{
HR(D3D11CreateDevice(nullptr, // Adapter
D3D_DRIVER_TYPE_HARDWARE,
nullptr, // Module
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
nullptr, 0, // Highest available feature level
D3D11_SDK_VERSION,
&direct3dDevice,
nullptr, // Actual feature level
nullptr)); // Device context
HR(direct3dDevice.As(&dxgiDevice));
HR(CreateDXGIFactory2(
DXGI_CREATE_FACTORY_DEBUG,
__uuidof(dxFactory),
reinterpret_cast<void**>(dxFactory.GetAddressOf())));
DXGI_SWAP_CHAIN_DESC1 description = {};
description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
description.BufferCount = 2;
description.SampleDesc.Count = 1;
description.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
RECT rect = {};
GetClientRect(hwnd, &rect);
description.Width = rect.right - rect.left;
description.Height = rect.bottom - rect.top;
HR(dxFactory->CreateSwapChainForComposition(dxgiDevice.Get(),
&description,
nullptr, // Don’t restrict
swapChain.GetAddressOf()));
D2D1_FACTORY_OPTIONS const options = { D2D1_DEBUG_LEVEL_INFORMATION };
HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
options,
d2Factory.GetAddressOf()));
// Create the Direct2D device that links back to the Direct3D device
HR(d2Factory->CreateDevice(dxgiDevice.Get(),
d2Device.GetAddressOf()));
// Create the Direct2D device context that is the actual render target
// and exposes drawing commands
ComPtr<ID2D1DeviceContext> dc;
HR(d2Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
dc.GetAddressOf()));
// Retrieve the swap chain's back buffer
ComPtr<IDXGISurface2> surface;
HR(swapChain->GetBuffer(
0, // index
__uuidof(surface),
reinterpret_cast<void**>(surface.GetAddressOf())));
// Create a Direct2D bitmap that points to the swap chain surface
D2D1_BITMAP_PROPERTIES1 properties = {};
properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
properties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
properties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET |
D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
ComPtr<ID2D1Bitmap1> bitmap;
HR(dc->CreateBitmapFromDxgiSurface(surface.Get(),
properties,
bitmap.GetAddressOf()));
// Point the device context to the bitmap for rendering
dc->SetTarget(bitmap.Get());
// Draw something
dc->BeginDraw();
dc->Clear();
ComPtr<ID2D1SolidColorBrush> brush;
D2D1_COLOR_F const brushColor = D2D1::ColorF(0.18f, // red
0.55f, // green
0.34f, // blue
0.75f); // alpha
HR(dc->CreateSolidColorBrush(brushColor,
brush.GetAddressOf()));
D2D1_POINT_2F const ellipseCenter = D2D1::Point2F(150.0f, // x
150.0f); // y
D2D1_ELLIPSE const ellipse = D2D1::Ellipse(ellipseCenter,
100.0f, // x radius
100.0f); // y radius
dc->FillEllipse(ellipse,
brush.Get());
HR(dc->EndDraw());
// Make the swap chain available to the composition engine
HR(swapChain->Present(1, // sync
0)); // flags
ComPtr<IDCompositionDevice> dcompDevice;
ComPtr<IDCompositionVisual> visual;
HR(DCompositionCreateDevice(
dxgiDevice.Get(),
__uuidof(dcompDevice),
reinterpret_cast<void**>(dcompDevice.GetAddressOf())));
ComPtr<IDCompositionDevice3> dcompDevice3;
dcompDevice->QueryInterface(__uuidof(IDCompositionDevice), (LPVOID*)&dcompDevice3);
ComPtr<IDCompositionGaussianBlurEffect> effect;
HR(dcompDevice3->CreateGaussianBlurEffect(&effect));
effect->SetStandardDeviation(10.0f);
HR(dcompDevice->CreateTargetForHwnd(hwnd,
true, // Top most
target.GetAddressOf()));
HR(dcompDevice->CreateVisual(visual.GetAddressOf()));
HR(visual->SetContent(swapChain.Get()));
HR(target->SetRoot(visual.Get()));
HR(dcompDevice->Commit());
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(WS_EX_NOREDIRECTIONBITMAP,
wc.lpszClassName, L"Sample",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
nullptr, nullptr, hInstance, nullptr);
if (hwnd == NULL)
{
return 0;
}
CreateVisual(hwnd);
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
我尝试更改每一段代码,但它仍然抛出异常。我是Directx的新手,代码中的IDCompositionDevice3
设备实际上是我自己创建的,我不知道它是对还是错,因为微软提供的文档中没有太多描述。
这是完整的项目代码:Direct Composition Blur
据推测,这是使用 WRL 的 ComPtr
。要访问其内部接口指针,您需要调用 GetAddressOf:
dcompDevice3->CreateGaussianBlurEffect(effect.GetAddressOf());
WRL 的 operator& 在返回弱引用时很可怕,它会阻止编译器捕获这种意外使用。
注意:C++/WinRT 提供了更安全的 COM 智能指针类型 (winrt::com_ptr),但没有为您提供尽可能多的 COM 支持。
有两个问题:
1.dcomp
实现似乎最奇怪,因为它成功地回答了这个问题,但 dcompDevice3 实际上以某种方式被破坏,因此崩溃:
ComPtr<IDCompositionDevice3> dcompDevice3;
HR(dcompDevice->QueryInterface(__uuidof(IDCompositionDevice), (LPVOID*)&dcompDevice3))
2.and 你的代码也很糟糕,应该是这样的:
HR(DCompositionCreateDevice3( // only this factory can give you an IDCompositionDevice3 implementation
dxgiDevice.Get(),
__uuidof(dcompDevice),
reinterpret_cast<void**>(dcompDevice.GetAddressOf())));
ComPtr<IDCompositionDevice3> dcompDevice3;
HR(dcompDevice->QueryInterface(__uuidof(IDCompositionDevice3), (LPVOID*)&dcompDevice3)); // use IDCompositionDevice3 here
现在应该可以了,至少,继续。
我正在做一个基于这篇文章使用直接合成的项目:
Windows with C++ : High-Performance Window Layering Using the Windows Composition Engine
我能够重新创建示例并且它正在运行。目前我正在尝试将 IDCompositionGaussianBlurEffect 应用到我的视觉 (variable: visual)
但编译器抛出访问冲突异常。有没有什么方法可以使用直接合成将模糊效果应用到我的视觉对象上。
异常:
Exception thrown at 0x6E695565 (dcomp.dll) in DirectComNoCom.exe: 0xC0000005: Access violation reading location 0x41200000.
在这一行抛出异常:
effect->SetStandardDeviation(10.0f);
完整代码如下:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <wrl.h>
using namespace Microsoft::WRL;
#include <dxgi1_3.h>
#include <d3d11_2.h>
#include <d2d1_2.h>
#include <d2d1_2helper.h>
#include <dcomp.h>
#pragma comment(lib, "dxgi")
#pragma comment(lib, "d3d11")
#pragma comment(lib, "d2d1")
#pragma comment(lib, "dcomp")
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
ComPtr<ID3D11Device> direct3dDevice;
ComPtr<IDXGIDevice> dxgiDevice;
ComPtr<IDXGIFactory2> dxFactory;
ComPtr<IDXGISwapChain1> swapChain;
ComPtr<ID2D1Factory2> d2Factory;
ComPtr<ID2D1Device1> d2Device;
ComPtr<IDCompositionTarget> target;
struct ComException
{
HRESULT result;
ComException(HRESULT const value) :
result(value)
{}
};
void HR(HRESULT const result)
{
if (S_OK != result)
{
throw ComException(result);
}
}
void CreateVisual(HWND hwnd)
{
HR(D3D11CreateDevice(nullptr, // Adapter
D3D_DRIVER_TYPE_HARDWARE,
nullptr, // Module
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
nullptr, 0, // Highest available feature level
D3D11_SDK_VERSION,
&direct3dDevice,
nullptr, // Actual feature level
nullptr)); // Device context
HR(direct3dDevice.As(&dxgiDevice));
HR(CreateDXGIFactory2(
DXGI_CREATE_FACTORY_DEBUG,
__uuidof(dxFactory),
reinterpret_cast<void**>(dxFactory.GetAddressOf())));
DXGI_SWAP_CHAIN_DESC1 description = {};
description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
description.BufferCount = 2;
description.SampleDesc.Count = 1;
description.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
RECT rect = {};
GetClientRect(hwnd, &rect);
description.Width = rect.right - rect.left;
description.Height = rect.bottom - rect.top;
HR(dxFactory->CreateSwapChainForComposition(dxgiDevice.Get(),
&description,
nullptr, // Don’t restrict
swapChain.GetAddressOf()));
D2D1_FACTORY_OPTIONS const options = { D2D1_DEBUG_LEVEL_INFORMATION };
HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
options,
d2Factory.GetAddressOf()));
// Create the Direct2D device that links back to the Direct3D device
HR(d2Factory->CreateDevice(dxgiDevice.Get(),
d2Device.GetAddressOf()));
// Create the Direct2D device context that is the actual render target
// and exposes drawing commands
ComPtr<ID2D1DeviceContext> dc;
HR(d2Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
dc.GetAddressOf()));
// Retrieve the swap chain's back buffer
ComPtr<IDXGISurface2> surface;
HR(swapChain->GetBuffer(
0, // index
__uuidof(surface),
reinterpret_cast<void**>(surface.GetAddressOf())));
// Create a Direct2D bitmap that points to the swap chain surface
D2D1_BITMAP_PROPERTIES1 properties = {};
properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
properties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
properties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET |
D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
ComPtr<ID2D1Bitmap1> bitmap;
HR(dc->CreateBitmapFromDxgiSurface(surface.Get(),
properties,
bitmap.GetAddressOf()));
// Point the device context to the bitmap for rendering
dc->SetTarget(bitmap.Get());
// Draw something
dc->BeginDraw();
dc->Clear();
ComPtr<ID2D1SolidColorBrush> brush;
D2D1_COLOR_F const brushColor = D2D1::ColorF(0.18f, // red
0.55f, // green
0.34f, // blue
0.75f); // alpha
HR(dc->CreateSolidColorBrush(brushColor,
brush.GetAddressOf()));
D2D1_POINT_2F const ellipseCenter = D2D1::Point2F(150.0f, // x
150.0f); // y
D2D1_ELLIPSE const ellipse = D2D1::Ellipse(ellipseCenter,
100.0f, // x radius
100.0f); // y radius
dc->FillEllipse(ellipse,
brush.Get());
HR(dc->EndDraw());
// Make the swap chain available to the composition engine
HR(swapChain->Present(1, // sync
0)); // flags
ComPtr<IDCompositionDevice> dcompDevice;
ComPtr<IDCompositionVisual> visual;
HR(DCompositionCreateDevice(
dxgiDevice.Get(),
__uuidof(dcompDevice),
reinterpret_cast<void**>(dcompDevice.GetAddressOf())));
ComPtr<IDCompositionDevice3> dcompDevice3;
dcompDevice->QueryInterface(__uuidof(IDCompositionDevice), (LPVOID*)&dcompDevice3);
ComPtr<IDCompositionGaussianBlurEffect> effect;
HR(dcompDevice3->CreateGaussianBlurEffect(&effect));
effect->SetStandardDeviation(10.0f);
HR(dcompDevice->CreateTargetForHwnd(hwnd,
true, // Top most
target.GetAddressOf()));
HR(dcompDevice->CreateVisual(visual.GetAddressOf()));
HR(visual->SetContent(swapChain.Get()));
HR(target->SetRoot(visual.Get()));
HR(dcompDevice->Commit());
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(WS_EX_NOREDIRECTIONBITMAP,
wc.lpszClassName, L"Sample",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
nullptr, nullptr, hInstance, nullptr);
if (hwnd == NULL)
{
return 0;
}
CreateVisual(hwnd);
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
我尝试更改每一段代码,但它仍然抛出异常。我是Directx的新手,代码中的IDCompositionDevice3
设备实际上是我自己创建的,我不知道它是对还是错,因为微软提供的文档中没有太多描述。
这是完整的项目代码:Direct Composition Blur
据推测,这是使用 WRL 的 ComPtr
。要访问其内部接口指针,您需要调用 GetAddressOf:
dcompDevice3->CreateGaussianBlurEffect(effect.GetAddressOf());
WRL 的 operator& 在返回弱引用时很可怕,它会阻止编译器捕获这种意外使用。
注意:C++/WinRT 提供了更安全的 COM 智能指针类型 (winrt::com_ptr),但没有为您提供尽可能多的 COM 支持。
有两个问题:
1.dcomp
实现似乎最奇怪,因为它成功地回答了这个问题,但 dcompDevice3 实际上以某种方式被破坏,因此崩溃:
ComPtr<IDCompositionDevice3> dcompDevice3;
HR(dcompDevice->QueryInterface(__uuidof(IDCompositionDevice), (LPVOID*)&dcompDevice3))
2.and 你的代码也很糟糕,应该是这样的:
HR(DCompositionCreateDevice3( // only this factory can give you an IDCompositionDevice3 implementation
dxgiDevice.Get(),
__uuidof(dcompDevice),
reinterpret_cast<void**>(dcompDevice.GetAddressOf())));
ComPtr<IDCompositionDevice3> dcompDevice3;
HR(dcompDevice->QueryInterface(__uuidof(IDCompositionDevice3), (LPVOID*)&dcompDevice3)); // use IDCompositionDevice3 here
现在应该可以了,至少,继续。