-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathd3d11_texture_dynamic.cpp
More file actions
186 lines (167 loc) · 6.83 KB
/
d3d11_texture_dynamic.cpp
File metadata and controls
186 lines (167 loc) · 6.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include "com/com_pointer.hpp"
#include "d3d11_device.hpp"
#include "d3d11_texture.hpp"
#include "dxmt_buffer.hpp"
#include "dxmt_dynamic.hpp"
#include "dxmt_staging.hpp"
#include "dxmt_texture.hpp"
#include "d3d11_resource.hpp"
#include "d3d11_enumerable.hpp"
namespace dxmt {
#pragma region DynamicTexture
struct Subresource {
Rc<Buffer> buffer;
Rc<DynamicBuffer> dynamic;
uint32_t bytes_per_row;
uint32_t bytes_per_depth;
};
template <typename tag_texture>
class DynamicTexture : public TResourceBase<tag_texture, IMTLMinLODClampable> {
private:
std::vector<Subresource> subresources_;
float min_lod = 0.0;
using SRVBase =
TResourceViewBase<tag_shader_resource_view<DynamicTexture<tag_texture>>>;
class TextureSRV : public SRVBase {
public:
TextureSRV(const TextureViewDescriptor &descriptor,
const tag_shader_resource_view<>::DESC1 *pDesc,
DynamicTexture *pResource, MTLD3D11Device *pDevice)
: SRVBase(pDesc, pResource, pDevice) {
this->texture_ = pResource->texture_.ptr();
this->view_id_ = this->texture_->createView(descriptor);
this->subset_ = ResourceSubsetState(
&descriptor,
this->texture_->miplevelCount(),
this->texture_->arrayLength()
);
}
};
public:
DynamicTexture(const tag_texture::DESC1 *pDesc, Rc<Texture> &&u_texture, MTLD3D11Device *pDevice, std::vector<Subresource> && subresources) :
TResourceBase<tag_texture, IMTLMinLODClampable>(*pDesc, pDevice),
subresources_(std::move(subresources)) {
this->texture_ = std::move(u_texture);
}
Rc<StagingResource> staging(UINT) final { return nullptr; }
Rc<DynamicBuffer> dynamicBuffer(UINT*, UINT*) final { return {}; }
Rc<DynamicLinearTexture> dynamicLinearTexture(UINT*, UINT*) final { return {}; };
Rc<DynamicBuffer> dynamicTexture(UINT subresource, UINT *bytes_per_row,
UINT *bytes_per_depth) final {
if (subresource < subresources_.size()) {
auto &sub = subresources_[subresource];
*bytes_per_row = sub.bytes_per_row;
*bytes_per_depth = sub.bytes_per_depth;
return sub.dynamic;
}
return {};
};
HRESULT
STDMETHODCALLTYPE
CreateShaderResourceView(const D3D11_SHADER_RESOURCE_VIEW_DESC1 *pDesc,
ID3D11ShaderResourceView1 **ppView) override {
D3D11_SHADER_RESOURCE_VIEW_DESC1 finalDesc;
if (FAILED(ExtractEntireResourceViewDescription(&this->desc, pDesc,
&finalDesc))) {
ERR("DynamicTexture: Failed to create SRV descriptor");
return E_INVALIDARG;
}
TextureViewDescriptor descriptor;
uint32_t arraySize;
if constexpr (std::is_same_v<typename tag_texture::DESC1, D3D11_TEXTURE3D_DESC1>) {
arraySize = this->desc.Depth;
} else {
arraySize = this->desc.ArraySize;
}
if (FAILED(InitializeAndNormalizeViewDescriptor(
this->m_parent, this->desc.MipLevels, arraySize, this->texture_.ptr(), finalDesc, descriptor
))) {
ERR("DynamicTexture: Failed to create texture SRV");
return E_FAIL;
}
if (!ppView) {
return S_FALSE;
}
*ppView = ref(new TextureSRV(descriptor, &finalDesc, this, this->m_parent));
return S_OK;
};
void SetMinLOD(float MinLod) override { min_lod = MinLod; }
float GetMinLOD() override { return min_lod; }
};
template <typename tag>
HRESULT CreateDynamicTextureInternal(MTLD3D11Device *pDevice,
const typename tag::DESC1 *pDesc,
const D3D11_SUBRESOURCE_DATA *pInitialData,
typename tag::COM_IMPL **ppTexture) {
WMTTextureInfo info;
typename tag::DESC1 finalDesc;
if (FAILED(CreateMTLTextureDescriptor(pDevice, pDesc, &finalDesc, &info))) {
return E_INVALIDARG;
}
std::vector<Subresource> subresources;
for (auto &sub : EnumerateSubresources(finalDesc)) {
uint32_t bpr, bpi, buf_len;
if (FAILED(GetLinearTextureLayout(pDevice, finalDesc, sub.MipLevel, bpr, bpi, buf_len))) {
return E_FAIL;
}
Flags<BufferAllocationFlag> buffer_flags;
buffer_flags.set(BufferAllocationFlag::CpuWriteCombined, BufferAllocationFlag::SuballocateFromOnePage);
#ifdef __i386__
buffer_flags.set(BufferAllocationFlag::CpuPlaced);
#endif
Subresource subresource;
subresource.buffer = new Buffer(buf_len, pDevice->GetMTLDevice());
subresource.buffer->rename(subresource.buffer->allocate(buffer_flags));
subresource.dynamic = new DynamicBuffer(subresource.buffer.ptr(), buffer_flags);
subresource.bytes_per_row = bpr;
subresource.bytes_per_depth = bpi;
D3D11_ASSERT(subresources.size() == sub.SubresourceId);
if (pInitialData) {
// FIXME: should buffer be initialized? in theory they won't be read anyway
}
subresources.push_back(std::move(subresource));
}
auto texture = Rc<Texture>(new Texture(info, pDevice->GetMTLDevice()));
Flags<TextureAllocationFlag> flags;
flags.set(TextureAllocationFlag::GpuManaged);
flags.set(TextureAllocationFlag::ShaderReadonly);
if (pInitialData) {
auto default_allocation = texture->allocate(flags);
InitializeTextureData(pDevice, default_allocation->texture(), finalDesc, pInitialData);
texture->rename(std::move(default_allocation));
*ppTexture =
reinterpret_cast<typename tag::COM_IMPL *>(
ref(new DynamicTexture<tag>(&finalDesc, std::move(texture), pDevice, std::move(subresources))));
} else {
texture->rename(texture->allocate(flags));
*ppTexture = reinterpret_cast<typename tag::COM_IMPL *>(
ref(new DynamicTexture<tag>(&finalDesc, std::move(texture), pDevice, std::move(subresources))));
}
return S_OK;
}
HRESULT
CreateDynamicTexture1D(MTLD3D11Device *pDevice,
const D3D11_TEXTURE1D_DESC *pDesc,
const D3D11_SUBRESOURCE_DATA *pInitialData,
ID3D11Texture1D **ppTexture) {
return CreateDynamicTextureInternal<tag_texture_1d>(pDevice, pDesc,
pInitialData, ppTexture);
}
HRESULT
CreateDynamicTexture2D(MTLD3D11Device *pDevice,
const D3D11_TEXTURE2D_DESC1 *pDesc,
const D3D11_SUBRESOURCE_DATA *pInitialData,
ID3D11Texture2D1 **ppTexture) {
return CreateDynamicTextureInternal<tag_texture_2d>(pDevice, pDesc,
pInitialData, ppTexture);
}
HRESULT
CreateDynamicTexture3D(MTLD3D11Device *pDevice,
const D3D11_TEXTURE3D_DESC1 *pDesc,
const D3D11_SUBRESOURCE_DATA *pInitialData,
ID3D11Texture3D1 **ppTexture) {
return CreateDynamicTextureInternal<tag_texture_3d>(pDevice, pDesc,
pInitialData, ppTexture);
}
#pragma endregion
} // namespace dxmt