21#include <wrl/client.h>
23#define GR_D3D_CALL_ERRCHECK(X) \
26 SkASSERT(SUCCEEDED(result)); \
27 if (!SUCCEEDED(result)) { \
28 SkDebugf("Failed Direct3D call. Error: 0x%08lx\n", result); \
32using namespace Microsoft::WRL;
42 ~D3D12WindowContext()
override;
43 void initializeContext();
44 void destroyContext();
48 return fDevice.get() !=
nullptr;
56 inline static constexpr int kNumFrames = 2;
68 unsigned int fBufferIndex;
71 uint64_t fFenceValues[kNumFrames];
78 this->initializeContext();
81D3D12WindowContext::~D3D12WindowContext() {
82 this->destroyContext();
85void D3D12WindowContext::initializeContext() {
87 sk_gpu_test::CreateD3DBackendContext(&backendContext);
88 fDevice = backendContext.
fDevice;
89 fQueue = backendContext.
fQueue;
91 fContext = GrDirectContext::MakeDirect3D(backendContext, fDisplayParams.fGrContextOptions);
96 GetWindowRect(fWindow, &windowRect);
97 unsigned int width = windowRect.right - windowRect.left;
98 unsigned int height = windowRect.bottom - windowRect.top;
100 UINT dxgiFactoryFlags = 0;
101 SkDEBUGCODE(dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;)
106 DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
107 swapChainDesc.BufferCount = kNumFrames;
108 swapChainDesc.Width =
width;
109 swapChainDesc.Height =
height;
110 swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
111 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
112 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
113 swapChainDesc.SampleDesc.Count = 1;
117 fQueue.get(), fWindow, &swapChainDesc,
nullptr,
nullptr, &swapChain));
124 fBufferIndex = fSwapChain->GetCurrentBackBufferIndex();
126 fSampleCount = fDisplayParams.fMSAASampleCount;
130 for (
int i = 0;
i < kNumFrames; ++
i) {
131 fFenceValues[
i] = 10000;
134 IID_PPV_ARGS(&fFence)));
143void D3D12WindowContext::setupSurfaces(
int width,
int height) {
147 D3D12_RESOURCE_STATE_PRESENT,
148 DXGI_FORMAT_R8G8B8A8_UNORM,
152 for (
int i = 0;
i < kNumFrames; ++
i) {
156 fBuffers[
i]->GetDesc().Height == (UINT64)
height);
158 info.fResource = fBuffers[
i];
159 if (fSampleCount > 1) {
166 fDisplayParams.fColorSpace,
167 &fDisplayParams.fSurfaceProps);
174 fDisplayParams.fColorSpace,
175 &fDisplayParams.fSurfaceProps);
180void D3D12WindowContext::destroyContext() {
181 CloseHandle(fFenceEvent);
182 fFence.reset(
nullptr);
184 for (
int i = 0;
i < kNumFrames; ++
i) {
185 fSurfaces[
i].reset(
nullptr);
186 fBuffers[
i].reset(
nullptr);
189 fSwapChain.reset(
nullptr);
190 fQueue.reset(
nullptr);
191 fDevice.reset(
nullptr);
196 const UINT64 currentFenceValue = fFenceValues[fBufferIndex];
197 fBufferIndex = fSwapChain->GetCurrentBackBufferIndex();
200 if (fFence->GetCompletedValue() < fFenceValues[fBufferIndex]) {
202 WaitForSingleObjectEx(fFenceEvent, INFINITE,
FALSE);
206 fFenceValues[fBufferIndex] = currentFenceValue + 1;
208 return fSurfaces[fBufferIndex];
211void D3D12WindowContext::onSwapBuffers() {
224void D3D12WindowContext::resize(
int width,
int height) {
230 for (
int i = 0;
i < kNumFrames; ++
i) {
232 if (fFence->GetCompletedValue() < fFenceValues[
i]) {
234 WaitForSingleObjectEx(fFenceEvent, INFINITE,
FALSE);
236 fSurfaces[
i].reset(
nullptr);
237 fBuffers[
i].reset(
nullptr);
241 DXGI_FORMAT_R8G8B8A8_UNORM, 0));
250 this->destroyContext();
252 this->initializeContext();
260 std::unique_ptr<WindowContext> ctx(
new D3D12WindowContext(hwnd,
params));
261 if (!ctx->isValid()) {
#define GR_D3D_CALL_ERRCHECK(X)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
@ kTopLeft_GrSurfaceOrigin
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
virtual sk_sp< SkSurface > getBackbufferSurface()=0
virtual void setDisplayParams(const DisplayParams ¶ms)=0
virtual void resize(int w, int h)=0
virtual void onSwapBuffers()=0
const EmbeddedViewParams * params
SK_API sk_sp< SkSurface > WrapBackendRenderTarget(GrRecordingContext *context, const GrBackendRenderTarget &backendRenderTarget, GrSurfaceOrigin origin, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, RenderTargetReleaseProc releaseProc=nullptr, ReleaseContext releaseContext=nullptr)
@ kPresent
back-end surface will be used for presenting to screen
SK_API sk_sp< SkSurface > WrapBackendTexture(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
std::unique_ptr< WindowContext > MakeD3D12ForWin(HWND hwnd, const DisplayParams ¶ms)
gr_cp< ID3D12Device > fDevice
gr_cp< ID3D12CommandQueue > fQueue