@@ -107,6 +107,31 @@ bool foeMaterialLoader::initializedGraphics() const noexcept {
107
107
return mGfxSession != FOE_NULL_HANDLE;
108
108
}
109
109
110
+ namespace {
111
+
112
+ bool processResourceReplacement (foeResource *pResource) {
113
+ bool replaced = false ;
114
+
115
+ if (*pResource == FOE_NULL_HANDLE)
116
+ return false ;
117
+
118
+ while (foeResourceGetType (*pResource) == FOE_RESOURCE_RESOURCE_TYPE_REPLACED) {
119
+ foeResource replacement = foeResourceGetReplacement (*pResource);
120
+
121
+ foeResourceIncrementUseCount (replacement);
122
+
123
+ foeResourceDecrementUseCount (*pResource);
124
+ foeResourceDecrementRefCount (*pResource);
125
+
126
+ *pResource = replacement;
127
+ replaced = true ;
128
+ }
129
+
130
+ return replaced;
131
+ }
132
+
133
+ } // namespace
134
+
110
135
void foeMaterialLoader::gfxMaintenance () {
111
136
// Process Delayed Data Destruction
112
137
mDestroySync .lock ();
@@ -144,45 +169,110 @@ void foeMaterialLoader::gfxMaintenance() {
144
169
std::vector<LoadData> stillLoading;
145
170
146
171
for (auto &it : toLoad) {
147
- // Check to see if what we need has been loaded yet
148
- std::array<foeResource, 2 > subResources = {
149
- it.data .fragmentShader ,
150
- it.data .image ,
151
- };
172
+ bool replacement;
173
+ foeResourceLoadState subResLoadState;
174
+
175
+ do {
176
+ // Check to see if what we need has been loaded yet
177
+ std::array<foeResource, 2 > subResources = {
178
+ it.data .fragmentShader ,
179
+ it.data .image ,
180
+ };
181
+ subResLoadState = worstResourceLoadState (subResources.size (), subResources.data ());
182
+
183
+ // Then perform any replacements after retreiving the load state
184
+ replacement = false ;
185
+ replacement = replacement || processResourceReplacement (&it.data .fragmentShader );
186
+ replacement = replacement || processResourceReplacement (&it.data .image );
187
+
188
+ // Repeat as long as replacements are occurring
189
+ } while (replacement);
190
+
191
+ // Verify the sub-resources are/have expected type
192
+ if (it.data .fragmentShader != FOE_NULL_HANDLE) {
193
+ if (foeResourceType type = foeResourceGetType (it.data .fragmentShader );
194
+ type != FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_SHADER &&
195
+ type != FOE_RESOURCE_RESOURCE_TYPE_REPLACED &&
196
+ type != FOE_RESOURCE_RESOURCE_TYPE_UNDEFINED &&
197
+ !foeResourceHasType (it.data .fragmentShader ,
198
+ FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_SHADER)) {
199
+ subResLoadState = FOE_RESOURCE_LOAD_STATE_FAILED;
200
+ }
201
+ }
152
202
153
- auto subResLoadState = worstResourceLoadState (subResources.size (), subResources.data ());
203
+ if (it.data .image != FOE_NULL_HANDLE) {
204
+ if (foeResourceType type = foeResourceGetType (it.data .fragmentShader );
205
+ type != FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_IMAGE &&
206
+ type != FOE_RESOURCE_RESOURCE_TYPE_REPLACED &&
207
+ type != FOE_RESOURCE_RESOURCE_TYPE_UNDEFINED &&
208
+ !foeResourceHasType (it.data .fragmentShader ,
209
+ FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_IMAGE)) {
210
+ subResLoadState = FOE_RESOURCE_LOAD_STATE_FAILED;
211
+ }
212
+ }
154
213
155
214
if (subResLoadState == FOE_RESOURCE_LOAD_STATE_LOADED) {
156
- { // Using the sub-resources that are loaded, and definition data, create the resource
157
- foeGfxShader fragShader =
158
- (it.data .fragmentShader != FOE_NULL_HANDLE)
159
- ? ((foeShader const *)foeResourceGetData (it.data .fragmentShader ))->shader
160
- : FOE_NULL_HANDLE;
161
-
162
- auto const *pMaterialCI =
163
- (foeMaterialCreateInfo const *)foeResourceCreateInfoGetData (it.createInfo );
164
-
165
- it.data .pGfxFragDescriptor = foeGfxVkGetFragmentDescriptor (
166
- mGfxFragmentDescriptorPool , pMaterialCI->pRasterizationSCI ,
167
- pMaterialCI->pDepthStencilSCI , pMaterialCI->pColourBlendSCI , fragShader);
168
- }
215
+ // Using the sub-resources that are loaded, and definition data, create the resource
216
+ foeGfxShader fragShader =
217
+ (it.data .fragmentShader != FOE_NULL_HANDLE)
218
+ ? ((foeShader const *)foeResourceGetTypeData (
219
+ it.data .fragmentShader , FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_SHADER))
220
+ ->shader
221
+ : FOE_NULL_HANDLE;
169
222
170
- VkResult vkResult = createDescriptorSet (&it.data );
171
- if (vkResult != VK_SUCCESS)
172
- goto DESCRIPTOR_CREATE_FAILED;
223
+ auto const *pMaterialCI =
224
+ (foeMaterialCreateInfo const *)foeResourceCreateInfoGetData (it.createInfo );
173
225
174
- // Everything's ready, load the resource
175
- auto moveFn = [](void *pSrc, void *pDst) {
176
- auto *pSrcData = (foeMaterial *)pSrc;
177
- new (pDst) foeMaterial (std::move (*pSrcData));
178
- };
226
+ it.data .pGfxFragDescriptor = foeGfxVkGetFragmentDescriptor (
227
+ mGfxFragmentDescriptorPool , pMaterialCI->pRasterizationSCI ,
228
+ pMaterialCI->pDepthStencilSCI , pMaterialCI->pColourBlendSCI , fragShader);
179
229
180
- it.pPostLoadFn (it.resource , {}, &it.data , moveFn, this ,
181
- foeMaterialLoader::unloadResource);
182
- foeResourceCreateInfoDecrementRefCount (it.createInfo );
230
+ VkResult vkResult = createDescriptorSet (&it.data );
231
+ if (vkResult != VK_SUCCESS) {
232
+ // Failed to load
233
+ it.pPostLoadFn (
234
+ it.resource ,
235
+ to_foeResult (FOE_GRAPHICS_RESOURCE_ERROR_MATERIAL_SUBRESOURCE_FAILED_TO_LOAD),
236
+ nullptr , nullptr , nullptr , nullptr );
237
+ foeResourceCreateInfoDecrementRefCount (it.createInfo );
238
+
239
+ // Unload the data we did get
240
+ if (it.data .fragmentShader != nullptr ) {
241
+ foeResourceDecrementUseCount (it.data .fragmentShader );
242
+ foeResourceDecrementRefCount (it.data .fragmentShader );
243
+ }
244
+ if (it.data .image != FOE_NULL_HANDLE) {
245
+ foeResourceDecrementUseCount (it.data .image );
246
+ foeResourceDecrementRefCount (it.data .image );
247
+ }
248
+ } else {
249
+ // Everything's ready, load the resource
250
+ auto moveFn = [](void *pSrc, void *pDst) {
251
+ auto *pSrcData = (foeMaterial *)pSrc;
252
+ new (pDst) foeMaterial (std::move (*pSrcData));
253
+ };
254
+
255
+ if (foeResourceGetType (it.resource ) == FOE_RESOURCE_RESOURCE_TYPE_UNDEFINED) {
256
+ // Need to replace the placeholder with the actual resource
257
+ foeResource newResource = foeResourcePoolLoadedReplace (
258
+ mResourcePool , foeResourceGetID (it.resource ),
259
+ FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_MATERIAL, sizeof (foeMaterial),
260
+ &it.data , moveFn, this , foeMaterialLoader::unloadResource);
261
+
262
+ if (newResource == FOE_NULL_HANDLE)
263
+ // @TODO - Handle failure
264
+ std::abort ();
265
+
266
+ foeResourceDecrementRefCount (it.resource );
267
+ foeResourceDecrementRefCount (newResource);
268
+ } else {
269
+ it.pPostLoadFn (it.resource , {}, &it.data , moveFn, this ,
270
+ foeMaterialLoader::unloadResource);
271
+ }
272
+
273
+ foeResourceCreateInfoDecrementRefCount (it.createInfo );
274
+ }
183
275
} else if (subResLoadState == FOE_RESOURCE_LOAD_STATE_FAILED) {
184
- DESCRIPTOR_CREATE_FAILED:
185
- // One of them failed to load, we're not proceeding with this resource
186
276
it.pPostLoadFn (
187
277
it.resource ,
188
278
to_foeResult (FOE_GRAPHICS_RESOURCE_ERROR_MATERIAL_SUBRESOURCE_FAILED_TO_LOAD),
@@ -242,10 +332,12 @@ void foeMaterialLoader::load(foeResource resource,
242
332
nullptr , nullptr , nullptr , nullptr );
243
333
foeResourceCreateInfoDecrementRefCount (createInfo);
244
334
return ;
245
- } else if (foeResourceGetType (resource) != FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_MATERIAL) {
335
+ } else if (foeResourceType type = foeResourceGetType (resource);
336
+ type != FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_MATERIAL &&
337
+ type != FOE_RESOURCE_RESOURCE_TYPE_UNDEFINED) {
246
338
FOE_LOG (foeGraphicsResource, FOE_LOG_LEVEL_ERROR,
247
339
" foeMaterialLoader - Cannot load {} as it is an incompatible type: {}" ,
248
- foeIdToString (foeResourceGetID (resource)), foeResourceGetType (resource) );
340
+ foeIdToString (foeResourceGetID (resource)), type );
249
341
250
342
pPostLoadFn (resource, to_foeResult (FOE_GRAPHICS_RESOURCE_ERROR_INCOMPATIBLE_RESOURCE_TYPE),
251
343
nullptr , nullptr , nullptr , nullptr );
@@ -266,13 +358,15 @@ void foeMaterialLoader::load(foeResource resource,
266
358
data.fragmentShader = foeResourcePoolFind (mResourcePool , pMaterialCI->fragmentShader );
267
359
268
360
if (data.fragmentShader == FOE_NULL_HANDLE)
269
- data.fragmentShader = foeResourcePoolAdd (
270
- mResourcePool , pMaterialCI->fragmentShader ,
271
- FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_SHADER, sizeof (foeShader));
361
+ data.fragmentShader =
362
+ foeResourcePoolAdd (mResourcePool , pMaterialCI->fragmentShader );
272
363
}
273
364
274
- if (foeResourceGetType (data.fragmentShader ) !=
275
- FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_SHADER) {
365
+ if (foeResourceType type = foeResourceGetType (data.fragmentShader );
366
+ type != FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_SHADER &&
367
+ type != FOE_RESOURCE_RESOURCE_TYPE_REPLACED &&
368
+ type != FOE_RESOURCE_RESOURCE_TYPE_UNDEFINED &&
369
+ !foeResourceHasType (data.fragmentShader , FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_SHADER)) {
276
370
result = to_foeResult (FOE_GRAPHICS_RESOURCE_ERROR_MATERIAL_SUBRESOURCE_INCOMPATIBLE);
277
371
goto LOAD_FAILED;
278
372
}
@@ -283,12 +377,14 @@ void foeMaterialLoader::load(foeResource resource,
283
377
data.image = foeResourcePoolFind (mResourcePool , pMaterialCI->image );
284
378
285
379
if (data.image == FOE_NULL_HANDLE)
286
- data.image = foeResourcePoolAdd (mResourcePool , pMaterialCI->image ,
287
- FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_IMAGE,
288
- sizeof (foeImage));
380
+ data.image = foeResourcePoolAdd (mResourcePool , pMaterialCI->image );
289
381
}
290
382
291
- if (foeResourceGetType (data.image ) != FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_IMAGE) {
383
+ if (foeResourceType type = foeResourceGetType (data.image );
384
+ type != FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_IMAGE &&
385
+ type != FOE_RESOURCE_RESOURCE_TYPE_REPLACED &&
386
+ type != FOE_RESOURCE_RESOURCE_TYPE_UNDEFINED &&
387
+ !foeResourceHasType (data.image , FOE_GRAPHICS_RESOURCE_STRUCTURE_TYPE_IMAGE)) {
292
388
result = to_foeResult (FOE_GRAPHICS_RESOURCE_ERROR_MATERIAL_SUBRESOURCE_INCOMPATIBLE);
293
389
goto LOAD_FAILED;
294
390
}
0 commit comments