Fix Metal backend crash when rendering external image before set (#1847)
This commit is contained in:
@@ -9,6 +9,7 @@ A new header is inserted each time a *tag* is created.
|
||||
- Added support for the latest version of emscripten.
|
||||
- gltfio: fixed blackness seen with default material.
|
||||
- Added ETC2 and BC compressed texture support to Metal backend.
|
||||
- Rendering a SAMPLER_EXTERNAL texture before setting an external image no longer results in GPU errors.
|
||||
|
||||
## v1.4.2
|
||||
|
||||
|
||||
@@ -85,6 +85,9 @@ struct MetalContext {
|
||||
// External textures.
|
||||
CVMetalTextureCacheRef textureCache = nullptr;
|
||||
|
||||
// Empty texture used to prevent GPU errors when a sampler has been bound without a texture.
|
||||
id<MTLTexture> emptyTexture = nil;
|
||||
|
||||
MetalBlitter* blitter = nullptr;
|
||||
|
||||
// Fences.
|
||||
@@ -101,6 +104,8 @@ id<CAMetalDrawable> acquireDrawable(MetalContext* context);
|
||||
|
||||
id<MTLCommandBuffer> acquireCommandBuffer(MetalContext* context);
|
||||
|
||||
id<MTLTexture> getOrCreateEmptyTexture(MetalContext* context);
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -63,6 +63,29 @@ id<MTLCommandBuffer> acquireCommandBuffer(MetalContext* context) {
|
||||
return commandBuffer;
|
||||
}
|
||||
|
||||
id<MTLTexture> getOrCreateEmptyTexture(MetalContext* context) {
|
||||
if (context->emptyTexture) {
|
||||
return context->emptyTexture;
|
||||
}
|
||||
|
||||
MTLTextureDescriptor* textureDescriptor = [MTLTextureDescriptor new];
|
||||
textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
textureDescriptor.width = 1;
|
||||
textureDescriptor.height = 1;
|
||||
id<MTLTexture> texture = [context->device newTextureWithDescriptor:textureDescriptor];
|
||||
|
||||
MTLRegion region = {
|
||||
{ 0, 0, 0 }, // MTLOrigin
|
||||
{ 1, 1, 1 } // MTLSize
|
||||
};
|
||||
uint8_t imageData[4] = {0, 0, 0, 0};
|
||||
[texture replaceRegion:region mipmapLevel:0 withBytes:imageData bytesPerRow:4];
|
||||
|
||||
context->emptyTexture = texture;
|
||||
|
||||
return context->emptyTexture;
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -73,6 +73,7 @@ MetalDriver::MetalDriver(backend::MetalPlatform* platform) noexcept
|
||||
|
||||
MetalDriver::~MetalDriver() noexcept {
|
||||
mContext->device = nil;
|
||||
mContext->emptyTexture = nil;
|
||||
CFRelease(mContext->textureCache);
|
||||
delete mContext->bufferPool;
|
||||
delete mContext->blitter;
|
||||
@@ -908,6 +909,12 @@ void MetalDriver::draw(backend::PipelineState ps, Handle<HwRenderPrimitive> rph)
|
||||
texturesToBind[binding] = metalTexture->externalImage.getMetalTextureForDraw();
|
||||
}
|
||||
|
||||
if (!texturesToBind[binding]) {
|
||||
utils::slog.w << "Warning: no texture bound at binding point " << (size_t) binding
|
||||
<< "." << utils::io::endl;
|
||||
texturesToBind[binding] = getOrCreateEmptyTexture(mContext);
|
||||
}
|
||||
|
||||
id <MTLSamplerState> samplerState = mContext->samplerStateCache.getOrCreateState(sampler->s);
|
||||
samplersToBind[binding] = samplerState;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user