1 /*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/ganesh/d3d/GrD3DTexture.h"
9
10 #include "src/gpu/ganesh/GrTexture.h"
11 #include "src/gpu/ganesh/d3d/GrD3DGpu.h"
12 #include "src/gpu/ganesh/d3d/GrD3DUtil.h"
13
14 #include "include/gpu/ganesh/d3d/GrD3DTypes.h"
15
16 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
GrD3DTexture(GrD3DGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,const GrD3DTextureResourceInfo & info,sk_sp<GrD3DResourceState> state,const GrD3DDescriptorHeap::CPUHandle & shaderResourceView,GrMipmapStatus mipmapStatus,std::string_view label)17 GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu,
18 skgpu::Budgeted budgeted,
19 SkISize dimensions,
20 const GrD3DTextureResourceInfo& info,
21 sk_sp<GrD3DResourceState> state,
22 const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
23 GrMipmapStatus mipmapStatus,
24 std::string_view label)
25 : GrSurface(gpu, dimensions, info.fProtected, label)
26 , GrD3DTextureResource(info, std::move(state))
27 , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipmapStatus, label)
28 , fShaderResourceView(shaderResourceView) {
29 SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == info.fLevelCount));
30 this->registerWithCache(budgeted);
31 if (GrDxgiFormatIsCompressed(info.fFormat)) {
32 this->setReadOnly();
33 }
34 }
35
GrD3DTexture(GrD3DGpu * gpu,SkISize dimensions,const GrD3DTextureResourceInfo & info,sk_sp<GrD3DResourceState> state,const GrD3DDescriptorHeap::CPUHandle & shaderResourceView,GrMipmapStatus mipmapStatus,GrWrapCacheable cacheable,GrIOType ioType,std::string_view label)36 GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info,
37 sk_sp<GrD3DResourceState> state,
38 const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
39 GrMipmapStatus mipmapStatus, GrWrapCacheable cacheable,
40 GrIOType ioType,
41 std::string_view label)
42 : GrSurface(gpu, dimensions, info.fProtected, label)
43 , GrD3DTextureResource(info, std::move(state))
44 , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipmapStatus, label)
45 , fShaderResourceView(shaderResourceView) {
46 SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == info.fLevelCount));
47 if (ioType == kRead_GrIOType) {
48 this->setReadOnly();
49 }
50 this->registerWithCacheWrapped(cacheable);
51 }
52
53 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
GrD3DTexture(GrD3DGpu * gpu,SkISize dimensions,const GrD3DTextureResourceInfo & info,sk_sp<GrD3DResourceState> state,const GrD3DDescriptorHeap::CPUHandle & shaderResourceView,GrMipmapStatus mipmapStatus,std::string_view label)54 GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu,
55 SkISize dimensions,
56 const GrD3DTextureResourceInfo& info,
57 sk_sp<GrD3DResourceState> state,
58 const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
59 GrMipmapStatus mipmapStatus,
60 std::string_view label)
61 : GrSurface(gpu, dimensions, info.fProtected, label)
62 , GrD3DTextureResource(info, state)
63 , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipmapStatus, label)
64 , fShaderResourceView(shaderResourceView) {
65 SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == info.fLevelCount));
66 }
67
MakeNewTexture(GrD3DGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,const D3D12_RESOURCE_DESC & desc,GrProtected isProtected,GrMipmapStatus mipmapStatus,std::string_view label)68 sk_sp<GrD3DTexture> GrD3DTexture::MakeNewTexture(GrD3DGpu* gpu,
69 skgpu::Budgeted budgeted,
70 SkISize dimensions,
71 const D3D12_RESOURCE_DESC& desc,
72 GrProtected isProtected,
73 GrMipmapStatus mipmapStatus,
74 std::string_view label) {
75 GrD3DTextureResourceInfo info;
76 if (!GrD3DTextureResource::InitTextureResourceInfo(gpu, desc,
77 D3D12_RESOURCE_STATE_COPY_DEST,
78 isProtected, nullptr, &info)) {
79 return nullptr;
80 }
81
82 sk_sp<GrD3DResourceState> state(
83 new GrD3DResourceState(static_cast<D3D12_RESOURCE_STATES>(info.fResourceState)));
84
85 GrD3DDescriptorHeap::CPUHandle shaderResourceView =
86 gpu->resourceProvider().createShaderResourceView(info.fResource.get());
87
88 GrD3DTexture* tex = new GrD3DTexture(gpu, budgeted, dimensions, info, std::move(state),
89 shaderResourceView,
90 mipmapStatus,
91 label);
92
93 return sk_sp<GrD3DTexture>(tex);
94 }
95
MakeWrappedTexture(GrD3DGpu * gpu,SkISize dimensions,GrWrapCacheable cacheable,GrIOType ioType,const GrD3DTextureResourceInfo & info,sk_sp<GrD3DResourceState> state)96 sk_sp<GrD3DTexture> GrD3DTexture::MakeWrappedTexture(GrD3DGpu* gpu,
97 SkISize dimensions,
98 GrWrapCacheable cacheable,
99 GrIOType ioType,
100 const GrD3DTextureResourceInfo& info,
101 sk_sp<GrD3DResourceState> state) {
102 // TODO: If a client uses their own heap to allocate, how do we manage that?
103 // Adopted textures require both image and allocation because we're responsible for freeing
104 //SkASSERT(info.fTexture &&
105 // (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
106
107 GrMipmapStatus mipmapStatus = info.fLevelCount > 1 ? GrMipmapStatus::kValid
108 : GrMipmapStatus::kNotAllocated;
109
110 GrD3DDescriptorHeap::CPUHandle shaderResourceView =
111 gpu->resourceProvider().createShaderResourceView(info.fResource.get());
112
113 return sk_sp<GrD3DTexture>(new GrD3DTexture(gpu, dimensions, info, std::move(state),
114 shaderResourceView, mipmapStatus, cacheable,
115 ioType,
116 /*label=*/"D3DWrappedTexture"));
117 }
118
MakeAliasingTexture(GrD3DGpu * gpu,sk_sp<GrD3DTexture> originalTexture,const D3D12_RESOURCE_DESC & newDesc,D3D12_RESOURCE_STATES resourceState)119 sk_sp<GrD3DTexture> GrD3DTexture::MakeAliasingTexture(GrD3DGpu* gpu,
120 sk_sp<GrD3DTexture> originalTexture,
121 const D3D12_RESOURCE_DESC& newDesc,
122 D3D12_RESOURCE_STATES resourceState) {
123 GrD3DTextureResourceInfo info = originalTexture->fInfo;
124 info.fResource = gpu->memoryAllocator()->createAliasingResource(info.fAlloc, 0, &newDesc,
125 resourceState, nullptr);
126 if (!info.fResource) {
127 return nullptr;
128 }
129 info.fResourceState = resourceState;
130
131 sk_sp<GrD3DResourceState> state(
132 new GrD3DResourceState(static_cast<D3D12_RESOURCE_STATES>(resourceState)));
133
134 GrD3DDescriptorHeap::CPUHandle shaderResourceView =
135 gpu->resourceProvider().createShaderResourceView(info.fResource.get());
136
137 GrD3DTexture* tex = new GrD3DTexture(gpu,
138 skgpu::Budgeted::kNo,
139 originalTexture->dimensions(),
140 info,
141 std::move(state),
142 shaderResourceView,
143 originalTexture->mipmapStatus(),
144 /*label=*/"AliasingTexture");
145 return sk_sp<GrD3DTexture>(tex);
146 }
147
onRelease()148 void GrD3DTexture::onRelease() {
149 GrD3DGpu* gpu = this->getD3DGpu();
150 gpu->resourceProvider().recycleShaderView(fShaderResourceView);
151 this->releaseResource(gpu);
152
153 INHERITED::onRelease();
154 }
155
onAbandon()156 void GrD3DTexture::onAbandon() {
157 GrD3DGpu* gpu = this->getD3DGpu();
158 gpu->resourceProvider().recycleShaderView(fShaderResourceView);
159 this->releaseResource(gpu);
160 INHERITED::onAbandon();
161 }
162
getBackendTexture() const163 GrBackendTexture GrD3DTexture::getBackendTexture() const {
164 return GrBackendTexture(this->width(), this->height(), fInfo, this->grD3DResourceState());
165 }
166
getD3DGpu() const167 GrD3DGpu* GrD3DTexture::getD3DGpu() const {
168 SkASSERT(!this->wasDestroyed());
169 return static_cast<GrD3DGpu*>(this->getGpu());
170 }
171
onSetLabel()172 void GrD3DTexture::onSetLabel() {
173 SkASSERT(this->d3dResource());
174 if (!this->getLabel().empty()) {
175 const std::wstring label = L"_Skia_" + GrD3DMultiByteToWide(this->getLabel());
176 this->d3dResource()->SetName(label.c_str());
177 }
178 }
179