Fix Metal backend crash when rendering external image before set (#1847)

This commit is contained in:
Ben Doherty
2019-11-05 09:23:58 -08:00
committed by GitHub
parent 7c0d3cdb10
commit dd45703d73
4 changed files with 36 additions and 0 deletions
+1
View File
@@ -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;
});