blob: d2e890f780a1f4336a51466acab87f8e5b936115 [file] [log] [blame]
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrD3DTypes_DEFINED
#define GrD3DTypes_DEFINED
// This file includes d3d12.h, which in turn includes windows.h, which redefines many
// common identifiers such as:
// * interface
// * small
// * near
// * far
// * CreateSemaphore
// * MemoryBarrier
//
// You should only include this header if you need the Direct3D definitions and are
// prepared to rename those identifiers.
#include "include/core/SkRefCnt.h"
#include "include/gpu/GrTypes.h"
#include <d3d12.h>
#include <dxgi1_4.h>
class GrD3DGpu;
/** Check if the argument is non-null, and if so, call obj->AddRef() and return obj.
*/
template <typename T> static inline T* GrSafeComAddRef(T* obj) {
if (obj) {
obj->AddRef();
}
return obj;
}
/** Check if the argument is non-null, and if so, call obj->Release()
*/
template <typename T> static inline void GrSafeComRelease(T* obj) {
if (obj) {
obj->Release();
}
}
template <typename T> class gr_cp {
public:
using element_type = T;
constexpr gr_cp() : fObject(nullptr) {}
constexpr gr_cp(std::nullptr_t) : fObject(nullptr) {}
/**
* Shares the underlying object by calling AddRef(), so that both the argument and the newly
* created gr_cp both have a reference to it.
*/
gr_cp(const gr_cp<T>& that) : fObject(GrSafeComAddRef(that.get())) {}
/**
* Move the underlying object from the argument to the newly created gr_cp. Afterwards only
* the new gr_cp will have a reference to the object, and the argument will point to null.
* No call to AddRef() or Release() will be made.
*/
gr_cp(gr_cp<T>&& that) : fObject(that.release()) {}
/**
* Adopt the bare object into the newly created gr_cp.
* No call to AddRef() or Release() will be made.
*/
explicit gr_cp(T* obj) {
fObject = obj;
}
/**
* Calls Release() on the underlying object pointer.
*/
~gr_cp() {
GrSafeComRelease(fObject);
SkDEBUGCODE(fObject = nullptr);
}
/**
* Shares the underlying object referenced by the argument by calling AddRef() on it. If this
* gr_cp previously had a reference to an object (i.e. not null) it will call Release()
* on that object.
*/
gr_cp<T>& operator=(const gr_cp<T>& that) {
if (this != &that) {
this->reset(GrSafeComAddRef(that.get()));
}
return *this;
}
/**
* Move the underlying object from the argument to the gr_cp. If the gr_cp
* previously held a reference to another object, Release() will be called on that object.
* No call to AddRef() will be made.
*/
gr_cp<T>& operator=(gr_cp<T>&& that) {
this->reset(that.release());
return *this;
}
explicit operator bool() const { return this->get() != nullptr; }
T* get() const { return fObject; }
T* operator->() const { return fObject; }
T** operator&() { return &fObject; }
/**
* Adopt the new object, and call Release() on any previously held object (if not null).
* No call to AddRef() will be made.
*/
void reset(T* object = nullptr) {
T* oldObject = fObject;
fObject = object;
GrSafeComRelease(oldObject);
}
/**
* Shares the new object by calling AddRef() on it. If this gr_cp previously had a
* reference to an object (i.e. not null) it will call Release() on that object.
*/
void retain(T* object) {
if (this->fObject != object) {
this->reset(GrSafeComAddRef(object));
}
}
/**
* Return the original object, and set the internal object to nullptr.
* The caller must assume ownership of the object, and manage its reference count directly.
* No call to Release() will be made.
*/
T* SK_WARN_UNUSED_RESULT release() {
T* obj = fObject;
fObject = nullptr;
return obj;
}
private:
T* fObject;
};
template <typename T> inline bool operator==(const gr_cp<T>& a,
const gr_cp<T>& b) {
return a.get() == b.get();
}
template <typename T> inline bool operator!=(const gr_cp<T>& a,
const gr_cp<T>& b) {
return a.get() != b.get();
}
// interface classes for the GPU memory allocator
class GrD3DAlloc : public SkRefCnt {
public:
~GrD3DAlloc() override = default;
};
class GrD3DMemoryAllocator : public SkRefCnt {
public:
virtual gr_cp<ID3D12Resource> createResource(D3D12_HEAP_TYPE, const D3D12_RESOURCE_DESC*,
D3D12_RESOURCE_STATES initialResourceState,
sk_sp<GrD3DAlloc>* allocation,
const D3D12_CLEAR_VALUE*) = 0;
virtual gr_cp<ID3D12Resource> createAliasingResource(sk_sp<GrD3DAlloc>& allocation,
uint64_t localOffset,
const D3D12_RESOURCE_DESC*,
D3D12_RESOURCE_STATES initialResourceState,
const D3D12_CLEAR_VALUE*) = 0;
};
// Note: there is no notion of Borrowed or Adopted resources in the D3D backend,
// so Ganesh will ref fResource once it's asked to wrap it.
// Clients are responsible for releasing their own ref to avoid memory leaks.
struct GrD3DTextureResourceInfo {
gr_cp<ID3D12Resource> fResource = nullptr;
sk_sp<GrD3DAlloc> fAlloc = nullptr;
D3D12_RESOURCE_STATES fResourceState = D3D12_RESOURCE_STATE_COMMON;
DXGI_FORMAT fFormat = DXGI_FORMAT_UNKNOWN;
uint32_t fSampleCount = 1;
uint32_t fLevelCount = 0;
unsigned int fSampleQualityPattern = DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
GrProtected fProtected = GrProtected::kNo;
GrD3DTextureResourceInfo() = default;
GrD3DTextureResourceInfo(ID3D12Resource* resource,
const sk_sp<GrD3DAlloc> alloc,
D3D12_RESOURCE_STATES resourceState,
DXGI_FORMAT format,
uint32_t sampleCount,
uint32_t levelCount,
unsigned int sampleQualityLevel,
GrProtected isProtected = GrProtected::kNo)
: fResource(resource)
, fAlloc(alloc)
, fResourceState(resourceState)
, fFormat(format)
, fSampleCount(sampleCount)
, fLevelCount(levelCount)
, fSampleQualityPattern(sampleQualityLevel)
, fProtected(isProtected) {}
GrD3DTextureResourceInfo(const GrD3DTextureResourceInfo& info,
D3D12_RESOURCE_STATES resourceState)
: fResource(info.fResource)
, fAlloc(info.fAlloc)
, fResourceState(resourceState)
, fFormat(info.fFormat)
, fSampleCount(info.fSampleCount)
, fLevelCount(info.fLevelCount)
, fSampleQualityPattern(info.fSampleQualityPattern)
, fProtected(info.fProtected) {}
#if GR_TEST_UTILS
bool operator==(const GrD3DTextureResourceInfo& that) const {
return fResource == that.fResource && fResourceState == that.fResourceState &&
fFormat == that.fFormat && fSampleCount == that.fSampleCount &&
fLevelCount == that.fLevelCount &&
fSampleQualityPattern == that.fSampleQualityPattern && fProtected == that.fProtected;
}
#endif
};
struct GrD3DFenceInfo {
GrD3DFenceInfo()
: fFence(nullptr)
, fValue(0) {
}
gr_cp<ID3D12Fence> fFence;
uint64_t fValue; // signal value for the fence
};
struct GrD3DSurfaceInfo {
uint32_t fSampleCount = 1;
uint32_t fLevelCount = 0;
GrProtected fProtected = GrProtected::kNo;
DXGI_FORMAT fFormat = DXGI_FORMAT_UNKNOWN;
unsigned int fSampleQualityPattern = DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
};
#endif