Add GrD3DDescriptorHeap.

Adds a wrapper around ID3D12DescriptorHeap, which manages allocations
of descriptors from the heap.

Change-Id: Idc3bdb43640639114de5d0520c339f9e0173e26f
Bug: skia:9935
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/286338
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2020-04-30 16:41:25 -04:00 committed by Skia Commit-Bot
parent 3c873afcd7
commit 2ba8ba26f9
4 changed files with 162 additions and 0 deletions

View File

@ -743,6 +743,8 @@ skia_direct3d_sources = [
"$_src/gpu/d3d/GrD3DCaps.h", "$_src/gpu/d3d/GrD3DCaps.h",
"$_src/gpu/d3d/GrD3DCommandList.cpp", "$_src/gpu/d3d/GrD3DCommandList.cpp",
"$_src/gpu/d3d/GrD3DCommandList.h", "$_src/gpu/d3d/GrD3DCommandList.h",
"$_src/gpu/d3d/GrD3DDescriptorHeap.cpp",
"$_src/gpu/d3d/GrD3DDescriptorHeap.h",
"$_src/gpu/d3d/GrD3DGpu.cpp", "$_src/gpu/d3d/GrD3DGpu.cpp",
"$_src/gpu/d3d/GrD3DGpu.h", "$_src/gpu/d3d/GrD3DGpu.h",
"$_src/gpu/d3d/GrD3DOpsRenderPass.cpp", "$_src/gpu/d3d/GrD3DOpsRenderPass.cpp",

View File

@ -0,0 +1,91 @@
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/d3d/GrD3DDescriptorHeap.h"
#include "src/gpu/d3d/GrD3DGpu.h"
sk_sp<GrD3DDescriptorHeap> GrD3DDescriptorHeap::Make(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type,
unsigned int numDescriptors,
D3D12_DESCRIPTOR_HEAP_FLAGS flags) {
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
heapDesc.Type = type;
heapDesc.NumDescriptors = numDescriptors;
heapDesc.Flags = flags;
ID3D12DescriptorHeap* heap;
gpu->device()->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&heap));
return sk_sp<GrD3DDescriptorHeap>(
new GrD3DDescriptorHeap(std::move(gr_cp<ID3D12DescriptorHeap>(heap)), heapDesc,
gpu->device()->GetDescriptorHandleIncrementSize(type)));
}
GrD3DDescriptorHeap::GrD3DDescriptorHeap(const gr_cp<ID3D12DescriptorHeap>& heap,
const D3D12_DESCRIPTOR_HEAP_DESC& descriptor,
unsigned int handleIncrementSize)
: fHeap(heap)
, fHandleIncrementSize(handleIncrementSize)
, fFreeBlocks(descriptor.NumDescriptors) {
// set all the bits in freeBlocks
for (UINT i = 0; i < descriptor.NumDescriptors; ++i) {
fFreeBlocks.set(i);
}
}
D3D12_CPU_DESCRIPTOR_HANDLE GrD3DDescriptorHeap::allocateCPUHandle() {
// valid only for non-shader-visible heaps
SkASSERT(!SkToBool(fHeap->GetDesc().Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
D3D12_CPU_DESCRIPTOR_HANDLE handle = fHeap->GetCPUDescriptorHandleForHeapStart();
int freeIndex = fFreeBlocks.leadingBitIndex();
SkASSERT(freeIndex >= 0);
handle.ptr += freeIndex * fHandleIncrementSize;
fFreeBlocks.clear(freeIndex);
return handle;
}
D3D12_GPU_DESCRIPTOR_HANDLE GrD3DDescriptorHeap::allocateGPUHandle() {
D3D12_GPU_DESCRIPTOR_HANDLE handle = fHeap->GetGPUDescriptorHandleForHeapStart();
int freeIndex = fFreeBlocks.leadingBitIndex();
SkASSERT(freeIndex >= 0);
handle.ptr += freeIndex * fHandleIncrementSize;
fFreeBlocks.clear(freeIndex);
return handle;
}
void GrD3DDescriptorHeap::freeCPUHandle(D3D12_CPU_DESCRIPTOR_HANDLE* handle) {
// valid only for non-shader-visible heaps
SkASSERT(!SkToBool(fHeap->GetDesc().Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
D3D12_CPU_DESCRIPTOR_HANDLE heapStart = fHeap->GetCPUDescriptorHandleForHeapStart();
// Make sure this handle belongs to this heap
SkASSERT(handle->ptr >= heapStart.ptr);
SIZE_T index = (handle->ptr - heapStart.ptr) / fHandleIncrementSize;
SkASSERT(index < fHeap->GetDesc().NumDescriptors);
fFreeBlocks.set(index);
handle->ptr = 0;
}
void GrD3DDescriptorHeap::freeGPUHandle(D3D12_GPU_DESCRIPTOR_HANDLE* handle) {
D3D12_GPU_DESCRIPTOR_HANDLE heapStart = fHeap->GetGPUDescriptorHandleForHeapStart();
// Make sure this handle belongs to this heap
SkASSERT(handle->ptr >= heapStart.ptr);
SIZE_T index = (handle->ptr - heapStart.ptr) / fHandleIncrementSize;
SkASSERT(index < fHeap->GetDesc().NumDescriptors);
fFreeBlocks.set(index);
handle->ptr = 0;
}
#ifdef SK_TRACE_MANAGED_RESOURCES
/** Output a human-readable dump of this resource's information
*/
void GrD3DDescriptorHeap::dumpInfo() const {
SkDebugf("GrD3DDescriptorHeap: %d (%d refs)\n", fHeap.get(), this->getRefCnt());
}
#endif

View File

@ -0,0 +1,47 @@
/*
* 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 GrD3DDescriptorHeap_DEFINED
#define GrD3DDescriptorHeap_DEFINED
#include "include/gpu/d3d/GrD3DTypes.h"
#include "src/gpu/GrManagedResource.h"
#include "src/utils/SkBitSet.h"
class GrD3DGpu;
class GrD3DDescriptorHeap : public GrManagedResource {
public:
static sk_sp<GrD3DDescriptorHeap> Make(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE,
unsigned int numDescriptors,
D3D12_DESCRIPTOR_HEAP_FLAGS);
~GrD3DDescriptorHeap() override = default;
D3D12_CPU_DESCRIPTOR_HANDLE allocateCPUHandle(); // valid only for non-shader-visible heaps
D3D12_GPU_DESCRIPTOR_HANDLE allocateGPUHandle();
void freeCPUHandle(D3D12_CPU_DESCRIPTOR_HANDLE*);
void freeGPUHandle(D3D12_GPU_DESCRIPTOR_HANDLE*);
#ifdef SK_TRACE_MANAGED_RESOURCES
/** Output a human-readable dump of this resource's information
*/
void dumpInfo() const override;
#endif
void freeGPUData() const override {}
private:
GrD3DDescriptorHeap(const gr_cp<ID3D12DescriptorHeap>&, const D3D12_DESCRIPTOR_HEAP_DESC&,
unsigned int handleIncrementSize);
gr_cp<ID3D12DescriptorHeap> fHeap;
size_t fHandleIncrementSize;
SkBitSet fFreeBlocks;
};
#endif

View File

@ -9,6 +9,7 @@
#define SkBitSet_DEFINED #define SkBitSet_DEFINED
#include "include/private/SkTemplates.h" #include "include/private/SkTemplates.h"
#include "src/core/SkMathPriv.h"
class SkBitSet { class SkBitSet {
public: public:
@ -28,6 +29,14 @@ public:
*chunk |= mask; *chunk |= mask;
} }
/** Set the value of the index-th bit to false. */
void clear(int index) {
uint32_t mask = ~(1 << (index & 31));
uint32_t* chunk = this->internalGet(index);
SkASSERT(chunk);
*chunk &= mask;
}
bool has(int index) const { bool has(int index) const {
const uint32_t* chunk = this->internalGet(index); const uint32_t* chunk = this->internalGet(index);
uint32_t mask = 1 << (index & 31); uint32_t mask = 1 << (index & 31);
@ -50,6 +59,19 @@ public:
} }
} }
// Returns the index of the first set bit
// Returns -1 if no bits are set
int leadingBitIndex() {
const uint32_t* data = fBitData.get();
for (unsigned i = 0; i < fDwordCount; ++i) {
if (uint32_t value = data[i]) { // There are set bits
int index = SkPrevLog2(value);
return index + i * 32;
}
}
return -1;
}
private: private:
std::unique_ptr<uint32_t, SkFunctionWrapper<void(void*), sk_free>> fBitData; std::unique_ptr<uint32_t, SkFunctionWrapper<void(void*), sk_free>> fBitData;
size_t fDwordCount; // Dword (32-bit) count of the bitset. size_t fDwordCount; // Dword (32-bit) count of the bitset.