dawn-cmake/src/dawn/native/metal/TextureMTL.h
Austin Eng 2c8bea1f9e Add a toggle to keep Metal depth stencil textures initialized
To avoid uninitialized reads of depth stencil data, where the Metal
driver incorrectly binds/loads the wrong depth stencil subresource,
always keep all depth stencil subresources initialized. This means
that textures are initialized on creation, and StoreOp::Discard is
never used - Store is used instead.

Texture initialized state is still set as-if the Discard occured, so
Dawn will try to zero-initialize the subresource if it is read from.
In many cases, this will work correctly, and the application will
read back 0, as expected. In some cases, Metal will bind the wrong
subresource, and the previous contents will be read. This is wrong,
but at least it is not uninitialized data.

Bug: dawn:838
Change-Id: I3cc87073d52de60283e3b683bbee7809db803018
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/119344
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Shrek Shao <shrekshao@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
2023-02-11 00:00:12 +00:00

118 lines
4.3 KiB
Objective-C

// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_DAWN_NATIVE_METAL_TEXTUREMTL_H_
#define SRC_DAWN_NATIVE_METAL_TEXTUREMTL_H_
#include <IOSurface/IOSurfaceRef.h>
#import <Metal/Metal.h>
#include <vector>
#include "dawn/native/Texture.h"
#include "dawn/common/CoreFoundationRef.h"
#include "dawn/common/NSRef.h"
#include "dawn/native/DawnNative.h"
#include "dawn/native/MetalBackend.h"
namespace dawn::native::metal {
class CommandRecordingContext;
class Device;
struct MTLSharedEventAndSignalValue;
MTLPixelFormat MetalPixelFormat(const DeviceBase* device, wgpu::TextureFormat format);
MaybeError ValidateIOSurfaceCanBeWrapped(const DeviceBase* device,
const TextureDescriptor* descriptor,
IOSurfaceRef ioSurface);
class Texture final : public TextureBase {
public:
static ResultOrError<Ref<Texture>> Create(Device* device, const TextureDescriptor* descriptor);
static ResultOrError<Ref<Texture>> CreateFromIOSurface(
Device* device,
const ExternalImageDescriptor* descriptor,
IOSurfaceRef ioSurface,
std::vector<MTLSharedEventAndSignalValue> waitEvents);
static Ref<Texture> CreateWrapping(Device* device,
const TextureDescriptor* descriptor,
NSPRef<id<MTLTexture>> wrapped);
Texture(DeviceBase* device, const TextureDescriptor* descriptor, TextureState state);
id<MTLTexture> GetMTLTexture() const;
IOSurfaceRef GetIOSurface();
NSPRef<id<MTLTexture>> CreateFormatView(wgpu::TextureFormat format);
bool ShouldKeepInitialized() const;
MTLBlitOption ComputeMTLBlitOption(Aspect aspect) const;
void EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
const SubresourceRange& range);
void SynchronizeTextureBeforeUse(CommandRecordingContext* commandContext);
void IOSurfaceEndAccess(ExternalImageIOSurfaceEndAccessDescriptor* descriptor);
private:
using TextureBase::TextureBase;
~Texture() override;
NSRef<MTLTextureDescriptor> CreateMetalTextureDescriptor() const;
MaybeError InitializeAsInternalTexture(const TextureDescriptor* descriptor);
MaybeError InitializeFromIOSurface(const ExternalImageDescriptor* descriptor,
const TextureDescriptor* textureDescriptor,
IOSurfaceRef ioSurface,
std::vector<MTLSharedEventAndSignalValue> waitEvents);
void InitializeAsWrapping(const TextureDescriptor* descriptor, NSPRef<id<MTLTexture>> wrapped);
void DestroyImpl() override;
MaybeError ClearTexture(CommandRecordingContext* commandContext,
const SubresourceRange& range,
TextureBase::ClearValue clearValue);
NSPRef<id<MTLTexture>> mMtlTexture;
MTLTextureUsage mMtlUsage;
CFRef<IOSurfaceRef> mIOSurface = nullptr;
std::vector<MTLSharedEventAndSignalValue> mWaitEvents;
};
class TextureView final : public TextureViewBase {
public:
static ResultOrError<Ref<TextureView>> Create(TextureBase* texture,
const TextureViewDescriptor* descriptor);
id<MTLTexture> GetMTLTexture() const;
struct AttachmentInfo {
NSPRef<id<MTLTexture>> texture;
uint32_t baseMipLevel;
uint32_t baseArrayLayer;
};
AttachmentInfo GetAttachmentInfo() const;
private:
using TextureViewBase::TextureViewBase;
MaybeError Initialize(const TextureViewDescriptor* descriptor);
void DestroyImpl() override;
NSPRef<id<MTLTexture>> mMtlTextureView;
};
} // namespace dawn::native::metal
#endif // SRC_DAWN_NATIVE_METAL_TEXTUREMTL_H_