blob: a611e3fd1c1a613b50a60f9f76bdd082c80aa451 [file] [log] [blame]
Corentin Wallez4a9ef4e2018-07-18 11:40:26 +02001// Copyright 2017 The Dawn Authors
Corentin Wallez0ba55502017-06-14 15:46:59 -04002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Corentin Wallezd37523f2018-07-24 13:53:51 +020015#include "dawn_native/metal/TextureMTL.h"
Corentin Wallez0ba55502017-06-14 15:46:59 -040016
Austin Eng0d661982020-01-16 00:12:10 +000017#include "common/Constants.h"
18#include "common/Math.h"
Corentin Wallezb495e482019-09-18 04:32:52 +000019#include "common/Platform.h"
Austin Eng0d661982020-01-16 00:12:10 +000020#include "dawn_native/DynamicUploader.h"
Austin Eng2cf5a082020-08-06 17:00:29 +000021#include "dawn_native/EnumMaskIterator.h"
Corentin Wallezd37523f2018-07-24 13:53:51 +020022#include "dawn_native/metal/DeviceMTL.h"
Austin Eng0d661982020-01-16 00:12:10 +000023#include "dawn_native/metal/StagingBufferMTL.h"
Austin Eng2cf5a082020-08-06 17:00:29 +000024#include "dawn_native/metal/UtilsMetal.h"
Corentin Wallez0ba55502017-06-14 15:46:59 -040025
Corentin Wallezc85ef792020-04-29 21:07:21 +000026#include <CoreVideo/CVPixelBuffer.h>
27
Corentin Wallez49a65d02018-07-24 16:45:45 +020028namespace dawn_native { namespace metal {
Corentin Wallez8308b1c2017-07-03 23:02:49 -040029
Austin Eng476e5cb2017-08-03 12:17:14 -040030 namespace {
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000031 bool UsageNeedsTextureView(wgpu::TextureUsage usage) {
32 constexpr wgpu::TextureUsage kUsageNeedsTextureView =
Brandon Jones27e17a62021-08-10 04:07:37 +000033 wgpu::TextureUsage::StorageBinding | wgpu::TextureUsage::TextureBinding;
Jiawei Shao5dee56f2018-12-29 10:47:28 +000034 return usage & kUsageNeedsTextureView;
35 }
36
Austin Eng75c50672021-06-24 02:01:46 +000037 MTLTextureUsage MetalTextureUsage(const Format& format,
38 wgpu::TextureUsage usage,
39 uint32_t sampleCount) {
Corentin Wallezf58d84d2017-11-24 14:12:44 -050040 MTLTextureUsage result = MTLTextureUsageUnknown; // This is 0
Corentin Wallez8308b1c2017-07-03 23:02:49 -040041
Brandon Jones27e17a62021-08-10 04:07:37 +000042 if (usage & (wgpu::TextureUsage::StorageBinding)) {
Corentin Wallez8308b1c2017-07-03 23:02:49 -040043 result |= MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead;
44 }
45
Brandon Jones27e17a62021-08-10 04:07:37 +000046 if (usage & (wgpu::TextureUsage::TextureBinding)) {
Corentin Wallez8308b1c2017-07-03 23:02:49 -040047 result |= MTLTextureUsageShaderRead;
Austin Enga0f17252020-11-04 15:27:11 +000048
49 // For sampling stencil aspect of combined depth/stencil. See TextureView
50 // constructor.
51 if (@available(macOS 10.12, iOS 10.0, *)) {
52 if (IsSubset(Aspect::Depth | Aspect::Stencil, format.aspects)) {
53 result |= MTLTextureUsagePixelFormatView;
54 }
55 }
Corentin Wallez8308b1c2017-07-03 23:02:49 -040056 }
57
Austin Eng75c50672021-06-24 02:01:46 +000058 // MTLTextureUsageRenderTarget is needed to clear multisample textures.
59 if (usage & (wgpu::TextureUsage::RenderAttachment) || sampleCount > 1) {
Corentin Wallez8308b1c2017-07-03 23:02:49 -040060 result |= MTLTextureUsageRenderTarget;
61 }
62
63 return result;
64 }
65
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000066 MTLTextureType MetalTextureViewType(wgpu::TextureViewDimension dimension,
Jiawei Shao865cad82019-04-09 08:04:59 +000067 unsigned int sampleCount) {
Jiawei Shaoe8d12b42018-10-26 06:29:38 +000068 switch (dimension) {
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000069 case wgpu::TextureViewDimension::e2D:
Jiawei Shao865cad82019-04-09 08:04:59 +000070 return (sampleCount > 1) ? MTLTextureType2DMultisample : MTLTextureType2D;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000071 case wgpu::TextureViewDimension::e2DArray:
Jiawei Shaoe8d12b42018-10-26 06:29:38 +000072 return MTLTextureType2DArray;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000073 case wgpu::TextureViewDimension::Cube:
Jiawei Shao5ab84ec2018-11-16 12:11:20 +000074 return MTLTextureTypeCube;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000075 case wgpu::TextureViewDimension::CubeArray:
Jiawei Shao5ab84ec2018-11-16 12:11:20 +000076 return MTLTextureTypeCubeArray;
Yunchao He1b9bcfc2021-02-03 16:36:59 +000077 case wgpu::TextureViewDimension::e3D:
78 return MTLTextureType3D;
Corentin Wallezeec9edf2020-09-24 14:56:50 +000079
80 case wgpu::TextureViewDimension::e1D:
Corentin Wallezeec9edf2020-09-24 14:56:50 +000081 case wgpu::TextureViewDimension::Undefined:
Jiawei Shaoe8d12b42018-10-26 06:29:38 +000082 UNREACHABLE();
Jiawei Shaoe8d12b42018-10-26 06:29:38 +000083 }
84 }
Jiawei Shao5dee56f2018-12-29 10:47:28 +000085
86 bool RequiresCreatingNewTextureView(const TextureBase* texture,
87 const TextureViewDescriptor* textureViewDescriptor) {
Corentin Walleza92f83b2019-06-21 10:16:15 +000088 if (texture->GetFormat().format != textureViewDescriptor->format) {
Jiawei Shao5dee56f2018-12-29 10:47:28 +000089 return true;
90 }
91
Jiawei Shao20301662019-02-21 00:45:19 +000092 if (texture->GetArrayLayers() != textureViewDescriptor->arrayLayerCount) {
Jiawei Shao5dee56f2018-12-29 10:47:28 +000093 return true;
94 }
95
Jiawei Shao20301662019-02-21 00:45:19 +000096 if (texture->GetNumMipLevels() != textureViewDescriptor->mipLevelCount) {
Jiawei Shao5dee56f2018-12-29 10:47:28 +000097 return true;
98 }
99
Austin Enga0f17252020-11-04 15:27:11 +0000100 if (IsSubset(Aspect::Depth | Aspect::Stencil, texture->GetFormat().aspects) &&
101 textureViewDescriptor->aspect == wgpu::TextureAspect::StencilOnly) {
102 return true;
103 }
104
Jiawei Shao5dee56f2018-12-29 10:47:28 +0000105 switch (textureViewDescriptor->dimension) {
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000106 case wgpu::TextureViewDimension::Cube:
107 case wgpu::TextureViewDimension::CubeArray:
Jiawei Shao5dee56f2018-12-29 10:47:28 +0000108 return true;
109 default:
110 break;
111 }
112
113 return false;
114 }
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000115
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000116 ResultOrError<wgpu::TextureFormat> GetFormatEquivalentToIOSurfaceFormat(uint32_t format) {
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000117 switch (format) {
Corentin Wallezc85ef792020-04-29 21:07:21 +0000118 case kCVPixelFormatType_32RGBA:
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000119 return wgpu::TextureFormat::RGBA8Unorm;
Corentin Wallezc85ef792020-04-29 21:07:21 +0000120 case kCVPixelFormatType_32BGRA:
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000121 return wgpu::TextureFormat::BGRA8Unorm;
Corentin Wallezc85ef792020-04-29 21:07:21 +0000122 case kCVPixelFormatType_TwoComponent8:
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000123 return wgpu::TextureFormat::RG8Unorm;
Corentin Wallezc85ef792020-04-29 21:07:21 +0000124 case kCVPixelFormatType_OneComponent8:
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000125 return wgpu::TextureFormat::R8Unorm;
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000126 default:
Brandon Joneseb0d9002021-10-22 17:39:20 +0000127 return DAWN_FORMAT_VALIDATION_ERROR("Unsupported IOSurface format (%x).",
128 format);
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000129 }
130 }
Corentin Wallezb495e482019-09-18 04:32:52 +0000131
132#if defined(DAWN_PLATFORM_MACOS)
133 MTLStorageMode kIOSurfaceStorageMode = MTLStorageModeManaged;
134#elif defined(DAWN_PLATFORM_IOS)
135 MTLStorageMode kIOSurfaceStorageMode = MTLStorageModePrivate;
136#else
137# error "Unsupported Apple platform."
138#endif
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000139 }
140
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000141 MTLPixelFormat MetalPixelFormat(wgpu::TextureFormat format) {
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000142 switch (format) {
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000143 case wgpu::TextureFormat::R8Unorm:
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000144 return MTLPixelFormatR8Unorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000145 case wgpu::TextureFormat::R8Snorm:
Corentin Wallez78430762019-07-08 09:28:51 +0000146 return MTLPixelFormatR8Snorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000147 case wgpu::TextureFormat::R8Uint:
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000148 return MTLPixelFormatR8Uint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000149 case wgpu::TextureFormat::R8Sint:
Corentin Wallez78430762019-07-08 09:28:51 +0000150 return MTLPixelFormatR8Sint;
151
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000152 case wgpu::TextureFormat::R16Uint:
Corentin Wallez78430762019-07-08 09:28:51 +0000153 return MTLPixelFormatR16Uint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000154 case wgpu::TextureFormat::R16Sint:
Corentin Wallez78430762019-07-08 09:28:51 +0000155 return MTLPixelFormatR16Sint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000156 case wgpu::TextureFormat::R16Float:
Corentin Wallez78430762019-07-08 09:28:51 +0000157 return MTLPixelFormatR16Float;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000158 case wgpu::TextureFormat::RG8Unorm:
Corentin Wallez78430762019-07-08 09:28:51 +0000159 return MTLPixelFormatRG8Unorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000160 case wgpu::TextureFormat::RG8Snorm:
Corentin Wallez78430762019-07-08 09:28:51 +0000161 return MTLPixelFormatRG8Snorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000162 case wgpu::TextureFormat::RG8Uint:
Corentin Wallez78430762019-07-08 09:28:51 +0000163 return MTLPixelFormatRG8Uint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000164 case wgpu::TextureFormat::RG8Sint:
Corentin Wallez78430762019-07-08 09:28:51 +0000165 return MTLPixelFormatRG8Sint;
166
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000167 case wgpu::TextureFormat::R32Uint:
Corentin Wallez78430762019-07-08 09:28:51 +0000168 return MTLPixelFormatR32Uint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000169 case wgpu::TextureFormat::R32Sint:
Corentin Wallez78430762019-07-08 09:28:51 +0000170 return MTLPixelFormatR32Sint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000171 case wgpu::TextureFormat::R32Float:
Corentin Wallez78430762019-07-08 09:28:51 +0000172 return MTLPixelFormatR32Float;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000173 case wgpu::TextureFormat::RG16Uint:
Corentin Wallez78430762019-07-08 09:28:51 +0000174 return MTLPixelFormatRG16Uint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000175 case wgpu::TextureFormat::RG16Sint:
Corentin Wallez78430762019-07-08 09:28:51 +0000176 return MTLPixelFormatRG16Sint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000177 case wgpu::TextureFormat::RG16Float:
Corentin Wallez78430762019-07-08 09:28:51 +0000178 return MTLPixelFormatRG16Float;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000179 case wgpu::TextureFormat::RGBA8Unorm:
Corentin Wallez78430762019-07-08 09:28:51 +0000180 return MTLPixelFormatRGBA8Unorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000181 case wgpu::TextureFormat::RGBA8UnormSrgb:
Corentin Wallez78430762019-07-08 09:28:51 +0000182 return MTLPixelFormatRGBA8Unorm_sRGB;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000183 case wgpu::TextureFormat::RGBA8Snorm:
Corentin Wallez78430762019-07-08 09:28:51 +0000184 return MTLPixelFormatRGBA8Snorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000185 case wgpu::TextureFormat::RGBA8Uint:
Corentin Wallez78430762019-07-08 09:28:51 +0000186 return MTLPixelFormatRGBA8Uint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000187 case wgpu::TextureFormat::RGBA8Sint:
Corentin Wallez78430762019-07-08 09:28:51 +0000188 return MTLPixelFormatRGBA8Sint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000189 case wgpu::TextureFormat::BGRA8Unorm:
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000190 return MTLPixelFormatBGRA8Unorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000191 case wgpu::TextureFormat::BGRA8UnormSrgb:
Corentin Wallez78430762019-07-08 09:28:51 +0000192 return MTLPixelFormatBGRA8Unorm_sRGB;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000193 case wgpu::TextureFormat::RGB10A2Unorm:
Corentin Wallez78430762019-07-08 09:28:51 +0000194 return MTLPixelFormatRGB10A2Unorm;
Corentin Wallez2f6e4ec2020-08-19 21:51:20 +0000195 case wgpu::TextureFormat::RG11B10Ufloat:
Corentin Wallez78430762019-07-08 09:28:51 +0000196 return MTLPixelFormatRG11B10Float;
Corentin Wallez2f6e4ec2020-08-19 21:51:20 +0000197 case wgpu::TextureFormat::RGB9E5Ufloat:
198 return MTLPixelFormatRGB9E5Float;
Corentin Wallez78430762019-07-08 09:28:51 +0000199
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000200 case wgpu::TextureFormat::RG32Uint:
Corentin Wallez78430762019-07-08 09:28:51 +0000201 return MTLPixelFormatRG32Uint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000202 case wgpu::TextureFormat::RG32Sint:
Corentin Wallez78430762019-07-08 09:28:51 +0000203 return MTLPixelFormatRG32Sint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000204 case wgpu::TextureFormat::RG32Float:
Corentin Wallez78430762019-07-08 09:28:51 +0000205 return MTLPixelFormatRG32Float;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000206 case wgpu::TextureFormat::RGBA16Uint:
Corentin Wallez78430762019-07-08 09:28:51 +0000207 return MTLPixelFormatRGBA16Uint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000208 case wgpu::TextureFormat::RGBA16Sint:
Corentin Wallez78430762019-07-08 09:28:51 +0000209 return MTLPixelFormatRGBA16Sint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000210 case wgpu::TextureFormat::RGBA16Float:
Corentin Wallez78430762019-07-08 09:28:51 +0000211 return MTLPixelFormatRGBA16Float;
212
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000213 case wgpu::TextureFormat::RGBA32Uint:
Corentin Wallez78430762019-07-08 09:28:51 +0000214 return MTLPixelFormatRGBA32Uint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000215 case wgpu::TextureFormat::RGBA32Sint:
Corentin Wallez78430762019-07-08 09:28:51 +0000216 return MTLPixelFormatRGBA32Sint;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000217 case wgpu::TextureFormat::RGBA32Float:
Corentin Wallez78430762019-07-08 09:28:51 +0000218 return MTLPixelFormatRGBA32Float;
219
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000220 case wgpu::TextureFormat::Depth32Float:
Corentin Wallez78430762019-07-08 09:28:51 +0000221 return MTLPixelFormatDepth32Float;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000222 case wgpu::TextureFormat::Depth24Plus:
Corentin Wallez78430762019-07-08 09:28:51 +0000223 return MTLPixelFormatDepth32Float;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000224 case wgpu::TextureFormat::Depth24PlusStencil8:
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000225 return MTLPixelFormatDepth32Float_Stencil8;
Dawn Autorollerd0effc02021-11-03 22:48:34 +0000226 case wgpu::TextureFormat::Depth16Unorm:
227 if (@available(macOS 10.12, iOS 13.0, *)) {
228 return MTLPixelFormatDepth16Unorm;
229 } else {
230 // TODO (dawn:1181): Allow non-conformant implementation on macOS 10.11
231 UNREACHABLE();
232 }
Corentin Wallez78430762019-07-08 09:28:51 +0000233
Corentin Wallezb629c502019-10-08 07:44:21 +0000234#if defined(DAWN_PLATFORM_MACOS)
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000235 case wgpu::TextureFormat::BC1RGBAUnorm:
Jiawei Shao55809702019-07-17 00:00:10 +0000236 return MTLPixelFormatBC1_RGBA;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000237 case wgpu::TextureFormat::BC1RGBAUnormSrgb:
Jiawei Shao55809702019-07-17 00:00:10 +0000238 return MTLPixelFormatBC1_RGBA_sRGB;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000239 case wgpu::TextureFormat::BC2RGBAUnorm:
Jiawei Shao55809702019-07-17 00:00:10 +0000240 return MTLPixelFormatBC2_RGBA;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000241 case wgpu::TextureFormat::BC2RGBAUnormSrgb:
Jiawei Shao55809702019-07-17 00:00:10 +0000242 return MTLPixelFormatBC2_RGBA_sRGB;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000243 case wgpu::TextureFormat::BC3RGBAUnorm:
Jiawei Shao55809702019-07-17 00:00:10 +0000244 return MTLPixelFormatBC3_RGBA;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000245 case wgpu::TextureFormat::BC3RGBAUnormSrgb:
Jiawei Shao55809702019-07-17 00:00:10 +0000246 return MTLPixelFormatBC3_RGBA_sRGB;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000247 case wgpu::TextureFormat::BC4RSnorm:
Jiawei Shao55809702019-07-17 00:00:10 +0000248 return MTLPixelFormatBC4_RSnorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000249 case wgpu::TextureFormat::BC4RUnorm:
Jiawei Shao55809702019-07-17 00:00:10 +0000250 return MTLPixelFormatBC4_RUnorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000251 case wgpu::TextureFormat::BC5RGSnorm:
Jiawei Shaoea2d5582019-07-10 23:58:13 +0000252 return MTLPixelFormatBC5_RGSnorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000253 case wgpu::TextureFormat::BC5RGUnorm:
Jiawei Shaoea2d5582019-07-10 23:58:13 +0000254 return MTLPixelFormatBC5_RGUnorm;
Corentin Wallez498d5ea2020-09-10 08:48:57 +0000255 case wgpu::TextureFormat::BC6HRGBFloat:
Jiawei Shao55809702019-07-17 00:00:10 +0000256 return MTLPixelFormatBC6H_RGBFloat;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000257 case wgpu::TextureFormat::BC6HRGBUfloat:
Jiawei Shao55809702019-07-17 00:00:10 +0000258 return MTLPixelFormatBC6H_RGBUfloat;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000259 case wgpu::TextureFormat::BC7RGBAUnorm:
Jiawei Shao55809702019-07-17 00:00:10 +0000260 return MTLPixelFormatBC7_RGBAUnorm;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000261 case wgpu::TextureFormat::BC7RGBAUnormSrgb:
Jiawei Shao55809702019-07-17 00:00:10 +0000262 return MTLPixelFormatBC7_RGBAUnorm_sRGB;
Loko Kungc7226a72021-08-31 00:15:45 +0000263#else
264 case wgpu::TextureFormat::BC1RGBAUnorm:
265 case wgpu::TextureFormat::BC1RGBAUnormSrgb:
266 case wgpu::TextureFormat::BC2RGBAUnorm:
267 case wgpu::TextureFormat::BC2RGBAUnormSrgb:
268 case wgpu::TextureFormat::BC3RGBAUnorm:
269 case wgpu::TextureFormat::BC3RGBAUnormSrgb:
270 case wgpu::TextureFormat::BC4RSnorm:
271 case wgpu::TextureFormat::BC4RUnorm:
272 case wgpu::TextureFormat::BC5RGSnorm:
273 case wgpu::TextureFormat::BC5RGUnorm:
274 case wgpu::TextureFormat::BC6HRGBFloat:
275 case wgpu::TextureFormat::BC6HRGBUfloat:
276 case wgpu::TextureFormat::BC7RGBAUnorm:
277 case wgpu::TextureFormat::BC7RGBAUnormSrgb:
Corentin Wallezb629c502019-10-08 07:44:21 +0000278#endif
Jiawei Shaoea2d5582019-07-10 23:58:13 +0000279
Loko Kungc7226a72021-08-31 00:15:45 +0000280 case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
281
282 case wgpu::TextureFormat::ETC2RGB8Unorm:
283 case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
284 case wgpu::TextureFormat::ETC2RGB8A1Unorm:
285 case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
286 case wgpu::TextureFormat::ETC2RGBA8Unorm:
287 case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
288 case wgpu::TextureFormat::EACR11Unorm:
289 case wgpu::TextureFormat::EACR11Snorm:
290 case wgpu::TextureFormat::EACRG11Unorm:
291 case wgpu::TextureFormat::EACRG11Snorm:
292
Loko Kung37a86492021-09-07 18:39:04 +0000293 case wgpu::TextureFormat::ASTC4x4Unorm:
294 case wgpu::TextureFormat::ASTC4x4UnormSrgb:
295 case wgpu::TextureFormat::ASTC5x4Unorm:
296 case wgpu::TextureFormat::ASTC5x4UnormSrgb:
297 case wgpu::TextureFormat::ASTC5x5Unorm:
298 case wgpu::TextureFormat::ASTC5x5UnormSrgb:
299 case wgpu::TextureFormat::ASTC6x5Unorm:
300 case wgpu::TextureFormat::ASTC6x5UnormSrgb:
301 case wgpu::TextureFormat::ASTC6x6Unorm:
302 case wgpu::TextureFormat::ASTC6x6UnormSrgb:
303 case wgpu::TextureFormat::ASTC8x5Unorm:
304 case wgpu::TextureFormat::ASTC8x5UnormSrgb:
305 case wgpu::TextureFormat::ASTC8x6Unorm:
306 case wgpu::TextureFormat::ASTC8x6UnormSrgb:
307 case wgpu::TextureFormat::ASTC8x8Unorm:
308 case wgpu::TextureFormat::ASTC8x8UnormSrgb:
309 case wgpu::TextureFormat::ASTC10x5Unorm:
310 case wgpu::TextureFormat::ASTC10x5UnormSrgb:
311 case wgpu::TextureFormat::ASTC10x6Unorm:
312 case wgpu::TextureFormat::ASTC10x6UnormSrgb:
313 case wgpu::TextureFormat::ASTC10x8Unorm:
314 case wgpu::TextureFormat::ASTC10x8UnormSrgb:
315 case wgpu::TextureFormat::ASTC10x10Unorm:
316 case wgpu::TextureFormat::ASTC10x10UnormSrgb:
317 case wgpu::TextureFormat::ASTC12x10Unorm:
318 case wgpu::TextureFormat::ASTC12x10UnormSrgb:
319 case wgpu::TextureFormat::ASTC12x12Unorm:
320 case wgpu::TextureFormat::ASTC12x12UnormSrgb:
321
Kai Ninomiyafa9ca442021-09-17 18:25:53 +0000322 // TODO(dawn:666): implement stencil8
Loko Kungc7226a72021-08-31 00:15:45 +0000323 case wgpu::TextureFormat::Stencil8:
324 case wgpu::TextureFormat::Undefined:
Jiawei Shaoc2750ab2019-06-01 02:30:51 +0000325 UNREACHABLE();
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000326 }
327 }
328
329 MaybeError ValidateIOSurfaceCanBeWrapped(const DeviceBase*,
330 const TextureDescriptor* descriptor,
331 IOSurfaceRef ioSurface,
332 uint32_t plane) {
333 // IOSurfaceGetPlaneCount can return 0 for non-planar IOSurfaces but we will treat
334 // non-planar like it is a single plane.
335 size_t surfacePlaneCount = std::max(size_t(1), IOSurfaceGetPlaneCount(ioSurface));
Brandon Joneseb0d9002021-10-22 17:39:20 +0000336 DAWN_INVALID_IF(plane >= surfacePlaneCount,
337 "IOSurface plane (%u) exceeds the surface's plane count (%u).", plane,
338 surfacePlaneCount);
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000339
Brandon Joneseb0d9002021-10-22 17:39:20 +0000340 DAWN_INVALID_IF(descriptor->dimension != wgpu::TextureDimension::e2D,
341 "Texture dimension (%s) is not %s.", descriptor->dimension,
342 wgpu::TextureDimension::e2D);
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000343
Brandon Joneseb0d9002021-10-22 17:39:20 +0000344 DAWN_INVALID_IF(descriptor->mipLevelCount != 1, "Mip level count (%u) is not 1.",
345 descriptor->mipLevelCount);
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000346
Brandon Joneseb0d9002021-10-22 17:39:20 +0000347 DAWN_INVALID_IF(descriptor->size.depthOrArrayLayers != 1,
348 "Array layer count (%u) is not 1.", descriptor->size.depthOrArrayLayers);
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000349
Brandon Joneseb0d9002021-10-22 17:39:20 +0000350 DAWN_INVALID_IF(descriptor->sampleCount != 1, "Sample count (%u) is not 1.",
351 descriptor->sampleCount);
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000352
Brandon Joneseb0d9002021-10-22 17:39:20 +0000353 uint32_t surfaceWidth = IOSurfaceGetWidthOfPlane(ioSurface, plane);
354 uint32_t surfaceHeight = IOSurfaceGetHeightOfPlane(ioSurface, plane);
355
356 DAWN_INVALID_IF(
357 descriptor->size.width != surfaceWidth || descriptor->size.height != surfaceHeight ||
358 descriptor->size.depthOrArrayLayers != 1,
359 "IOSurface size (width: %u, height %u, depth: 1) doesn't match descriptor size %s.",
360 surfaceWidth, surfaceHeight, &descriptor->size);
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000361
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000362 wgpu::TextureFormat ioSurfaceFormat;
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000363 DAWN_TRY_ASSIGN(ioSurfaceFormat,
364 GetFormatEquivalentToIOSurfaceFormat(IOSurfaceGetPixelFormat(ioSurface)));
Brandon Joneseb0d9002021-10-22 17:39:20 +0000365 DAWN_INVALID_IF(descriptor->format != ioSurfaceFormat,
366 "IOSurface format (%s) doesn't match the descriptor format (%s).",
367 ioSurfaceFormat, descriptor->format);
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000368
369 return {};
370 }
371
Austin Eng0eff5982021-07-27 19:59:58 +0000372 NSRef<MTLTextureDescriptor> Texture::CreateMetalTextureDescriptor() const {
Corentin Wallez0055d952020-11-16 23:07:56 +0000373 NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]);
374 MTLTextureDescriptor* mtlDesc = mtlDescRef.Get();
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000375
Austin Eng0eff5982021-07-27 19:59:58 +0000376 mtlDesc.width = GetWidth();
377 mtlDesc.height = GetHeight();
378 mtlDesc.sampleCount = GetSampleCount();
Corentin Wallezcaec4ab2020-08-18 15:39:06 +0000379 // TODO: add MTLTextureUsagePixelFormatView when needed when we support format
380 // reinterpretation.
Austin Eng0eff5982021-07-27 19:59:58 +0000381 mtlDesc.usage = MetalTextureUsage(GetFormat(), GetInternalUsage(), GetSampleCount());
382 mtlDesc.pixelFormat = MetalPixelFormat(GetFormat().format);
383 mtlDesc.mipmapLevelCount = GetNumMipLevels();
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000384 mtlDesc.storageMode = MTLStorageModePrivate;
385
Corentin Wallez8a5325c2020-06-15 09:57:51 +0000386 // Choose the correct MTLTextureType and paper over differences in how the array layer count
387 // is specified.
Austin Eng0eff5982021-07-27 19:59:58 +0000388 switch (GetDimension()) {
Corentin Wallez8a5325c2020-06-15 09:57:51 +0000389 case wgpu::TextureDimension::e2D:
Austin Eng0eff5982021-07-27 19:59:58 +0000390 mtlDesc.depth = 1;
391 mtlDesc.arrayLength = GetArrayLayers();
392 if (mtlDesc.arrayLength > 1) {
Corentin Wallez8a5325c2020-06-15 09:57:51 +0000393 ASSERT(mtlDesc.sampleCount == 1);
394 mtlDesc.textureType = MTLTextureType2DArray;
Austin Eng0eff5982021-07-27 19:59:58 +0000395 } else if (mtlDesc.sampleCount > 1) {
396 mtlDesc.textureType = MTLTextureType2DMultisample;
Corentin Wallez8a5325c2020-06-15 09:57:51 +0000397 } else {
Austin Eng0eff5982021-07-27 19:59:58 +0000398 mtlDesc.textureType = MTLTextureType2D;
Corentin Wallez8a5325c2020-06-15 09:57:51 +0000399 }
400 break;
Yunchao He1b9bcfc2021-02-03 16:36:59 +0000401 case wgpu::TextureDimension::e3D:
Austin Eng0eff5982021-07-27 19:59:58 +0000402 mtlDesc.depth = GetDepth();
403 mtlDesc.arrayLength = 1;
Yunchao He1b9bcfc2021-02-03 16:36:59 +0000404 ASSERT(mtlDesc.sampleCount == 1);
405 mtlDesc.textureType = MTLTextureType3D;
406 break;
Corentin Wallez8a5325c2020-06-15 09:57:51 +0000407
Corentin Wallezeec9edf2020-09-24 14:56:50 +0000408 case wgpu::TextureDimension::e1D:
Corentin Wallez8a5325c2020-06-15 09:57:51 +0000409 UNREACHABLE();
410 }
Jiawei Shao865cad82019-04-09 08:04:59 +0000411
Corentin Wallez0055d952020-11-16 23:07:56 +0000412 return mtlDescRef;
Corentin Wallez0ba55502017-06-14 15:46:59 -0400413 }
414
Corentin Wallez50f99582021-03-31 18:36:32 +0000415 // static
416 ResultOrError<Ref<Texture>> Texture::Create(Device* device,
417 const TextureDescriptor* descriptor) {
Corentin Wallez03f94372021-07-21 09:34:28 +0000418 Ref<Texture> texture =
419 AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal));
420 DAWN_TRY(texture->InitializeAsInternalTexture(descriptor));
421 return texture;
Corentin Wallez50f99582021-03-31 18:36:32 +0000422 }
423
Corentin Wallez03f94372021-07-21 09:34:28 +0000424 // static
425 ResultOrError<Ref<Texture>> Texture::CreateFromIOSurface(
426 Device* device,
427 const ExternalImageDescriptor* descriptor,
428 IOSurfaceRef ioSurface,
429 uint32_t plane) {
430 const TextureDescriptor* textureDescriptor =
431 reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
432
433 Ref<Texture> texture =
434 AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedInternal));
435 DAWN_TRY(texture->InitializeFromIOSurface(descriptor, textureDescriptor, ioSurface, plane));
436 return texture;
437 }
438
439 // static
440 Ref<Texture> Texture::CreateWrapping(Device* device,
441 const TextureDescriptor* descriptor,
442 NSPRef<id<MTLTexture>> wrapped) {
443 Ref<Texture> texture =
444 AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal));
445 texture->InitializeAsWrapping(descriptor, std::move(wrapped));
446 return texture;
447 }
448
449 MaybeError Texture::InitializeAsInternalTexture(const TextureDescriptor* descriptor) {
450 Device* device = ToBackend(GetDevice());
451
Austin Eng0eff5982021-07-27 19:59:58 +0000452 NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor();
Corentin Wallez03f94372021-07-21 09:34:28 +0000453 mMtlUsage = [*mtlDesc usage];
Corentin Wallez0055d952020-11-16 23:07:56 +0000454 mMtlTexture =
455 AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()]);
Corentin Wallez03f94372021-07-21 09:34:28 +0000456
457 if (mMtlTexture == nil) {
458 return DAWN_OUT_OF_MEMORY_ERROR("Failed to allocate texture.");
459 }
Austin Eng0d661982020-01-16 00:12:10 +0000460
461 if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
Corentin Wallez03f94372021-07-21 09:34:28 +0000462 DAWN_TRY(ClearTexture(device->GetPendingCommandContext(), GetAllSubresources(),
463 TextureBase::ClearValue::NonZero));
Austin Eng0d661982020-01-16 00:12:10 +0000464 }
Corentin Wallez03f94372021-07-21 09:34:28 +0000465
466 return {};
Corentin Wallez0ba55502017-06-14 15:46:59 -0400467 }
468
Corentin Wallez03f94372021-07-21 09:34:28 +0000469 void Texture::InitializeAsWrapping(const TextureDescriptor* descriptor,
470 NSPRef<id<MTLTexture>> wrapped) {
Austin Eng0eff5982021-07-27 19:59:58 +0000471 NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor();
Austin Eng75c50672021-06-24 02:01:46 +0000472 mMtlUsage = [*mtlDesc usage];
Corentin Wallez03f94372021-07-21 09:34:28 +0000473 mMtlTexture = std::move(wrapped);
Kai Ninomiya35bf4242017-07-19 15:41:17 -0700474 }
475
Corentin Wallez03f94372021-07-21 09:34:28 +0000476 MaybeError Texture::InitializeFromIOSurface(const ExternalImageDescriptor* descriptor,
477 const TextureDescriptor* textureDescriptor,
478 IOSurfaceRef ioSurface,
479 uint32_t plane) {
480 Device* device = ToBackend(GetDevice());
481
Austin Eng0eff5982021-07-27 19:59:58 +0000482 NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor();
Corentin Wallez0055d952020-11-16 23:07:56 +0000483 [*mtlDesc setStorageMode:kIOSurfaceStorageMode];
484
Corentin Wallez03f94372021-07-21 09:34:28 +0000485 mMtlUsage = [*mtlDesc usage];
Corentin Wallez0055d952020-11-16 23:07:56 +0000486 mMtlTexture = AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()
487 iosurface:ioSurface
488 plane:plane]);
Austin Eng0d661982020-01-16 00:12:10 +0000489
Austin Eng0b297322020-09-22 20:10:46 +0000490 SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
Corentin Wallez03f94372021-07-21 09:34:28 +0000491
492 return {};
Corentin Wallez0cdf9e02019-03-01 12:01:18 +0000493 }
494
Corentin Wallez0ba55502017-06-14 15:46:59 -0400495 Texture::~Texture() {
Natasha Lee20b0c332019-04-01 19:49:04 +0000496 DestroyInternal();
Natasha Leecae68ff2019-03-27 22:04:10 +0000497 }
498
499 void Texture::DestroyImpl() {
Corentin Wallez0055d952020-11-16 23:07:56 +0000500 mMtlTexture = nullptr;
Corentin Wallez0ba55502017-06-14 15:46:59 -0400501 }
502
503 id<MTLTexture> Texture::GetMTLTexture() {
Corentin Wallez0055d952020-11-16 23:07:56 +0000504 return mMtlTexture.Get();
Corentin Wallez0ba55502017-06-14 15:46:59 -0400505 }
506
Austin Eng26468c42021-05-08 16:01:16 +0000507 MaybeError Texture::ClearTexture(CommandRecordingContext* commandContext,
508 const SubresourceRange& range,
Austin Eng0d661982020-01-16 00:12:10 +0000509 TextureBase::ClearValue clearValue) {
510 Device* device = ToBackend(GetDevice());
511
Austin Eng0d661982020-01-16 00:12:10 +0000512 const uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
513 const double dClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.0 : 1.0;
514
Austin Eng75c50672021-06-24 02:01:46 +0000515 if ((mMtlUsage & MTLTextureUsageRenderTarget) != 0) {
Austin Eng0d661982020-01-16 00:12:10 +0000516 ASSERT(GetFormat().isRenderable);
517
518 // End the blit encoder if it is open.
519 commandContext->EndBlit();
520
521 if (GetFormat().HasDepthOrStencil()) {
522 // Create a render pass to clear each subresource.
Yunchao He5fafb492020-06-12 00:37:31 +0000523 for (uint32_t level = range.baseMipLevel;
524 level < range.baseMipLevel + range.levelCount; ++level) {
525 for (uint32_t arrayLayer = range.baseArrayLayer;
526 arrayLayer < range.baseArrayLayer + range.layerCount; arrayLayer++) {
Austin Eng0d661982020-01-16 00:12:10 +0000527 if (clearValue == TextureBase::ClearValue::Zero &&
Austin Eng2cf5a082020-08-06 17:00:29 +0000528 IsSubresourceContentInitialized(SubresourceRange::SingleMipAndLayer(
529 level, arrayLayer, range.aspects))) {
Austin Eng0d661982020-01-16 00:12:10 +0000530 // Skip lazy clears if already initialized.
531 continue;
532 }
533
Corentin Wallez0055d952020-11-16 23:07:56 +0000534 // Note that this creates a descriptor that's autoreleased so we don't use
535 // AcquireNSRef
536 NSRef<MTLRenderPassDescriptor> descriptorRef =
Austin Eng0d661982020-01-16 00:12:10 +0000537 [MTLRenderPassDescriptor renderPassDescriptor];
Corentin Wallez0055d952020-11-16 23:07:56 +0000538 MTLRenderPassDescriptor* descriptor = descriptorRef.Get();
Austin Eng0d661982020-01-16 00:12:10 +0000539
Austin Eng2cf5a082020-08-06 17:00:29 +0000540 // At least one aspect needs clearing. Iterate the aspects individually to
541 // determine which to clear.
542 for (Aspect aspect : IterateEnumMask(range.aspects)) {
543 if (clearValue == TextureBase::ClearValue::Zero &&
544 IsSubresourceContentInitialized(SubresourceRange::SingleMipAndLayer(
545 level, arrayLayer, aspect))) {
546 // Skip lazy clears if already initialized.
547 continue;
548 }
549
Austin Engfd783ce2021-05-18 21:51:33 +0000550 ASSERT(GetDimension() == wgpu::TextureDimension::e2D);
Austin Eng2cf5a082020-08-06 17:00:29 +0000551 switch (aspect) {
552 case Aspect::Depth:
553 descriptor.depthAttachment.texture = GetMTLTexture();
Austin Eng600f6f52020-12-03 16:55:53 +0000554 descriptor.depthAttachment.level = level;
555 descriptor.depthAttachment.slice = arrayLayer;
Austin Eng2cf5a082020-08-06 17:00:29 +0000556 descriptor.depthAttachment.loadAction = MTLLoadActionClear;
557 descriptor.depthAttachment.storeAction = MTLStoreActionStore;
558 descriptor.depthAttachment.clearDepth = dClearColor;
559 break;
560 case Aspect::Stencil:
561 descriptor.stencilAttachment.texture = GetMTLTexture();
Austin Eng600f6f52020-12-03 16:55:53 +0000562 descriptor.stencilAttachment.level = level;
563 descriptor.stencilAttachment.slice = arrayLayer;
Austin Eng2cf5a082020-08-06 17:00:29 +0000564 descriptor.stencilAttachment.loadAction = MTLLoadActionClear;
565 descriptor.stencilAttachment.storeAction = MTLStoreActionStore;
566 descriptor.stencilAttachment.clearStencil =
567 static_cast<uint32_t>(clearColor);
568 break;
569 default:
570 UNREACHABLE();
Austin Eng2cf5a082020-08-06 17:00:29 +0000571 }
Austin Eng0d661982020-01-16 00:12:10 +0000572 }
573
574 commandContext->BeginRender(descriptor);
575 commandContext->EndRender();
576 }
577 }
578 } else {
579 ASSERT(GetFormat().IsColor());
Yunchao He5fafb492020-06-12 00:37:31 +0000580 for (uint32_t level = range.baseMipLevel;
581 level < range.baseMipLevel + range.levelCount; ++level) {
Corentin Wallezda6dccd2020-05-29 07:37:48 +0000582 // Create multiple render passes with each subresource as a color attachment to
583 // clear them all. Only do this for array layers to ensure all attachments have
584 // the same size.
Corentin Wallez0055d952020-11-16 23:07:56 +0000585 NSRef<MTLRenderPassDescriptor> descriptor;
Corentin Wallezda6dccd2020-05-29 07:37:48 +0000586 uint32_t attachment = 0;
587
Austin Engfd783ce2021-05-18 21:51:33 +0000588 uint32_t numZSlices = GetMipLevelVirtualSize(level).depthOrArrayLayers;
589
Yunchao He5fafb492020-06-12 00:37:31 +0000590 for (uint32_t arrayLayer = range.baseArrayLayer;
591 arrayLayer < range.baseArrayLayer + range.layerCount; arrayLayer++) {
Austin Eng0d661982020-01-16 00:12:10 +0000592 if (clearValue == TextureBase::ClearValue::Zero &&
Austin Eng2cf5a082020-08-06 17:00:29 +0000593 IsSubresourceContentInitialized(SubresourceRange::SingleMipAndLayer(
594 level, arrayLayer, Aspect::Color))) {
Austin Eng0d661982020-01-16 00:12:10 +0000595 // Skip lazy clears if already initialized.
596 continue;
597 }
598
Austin Engfd783ce2021-05-18 21:51:33 +0000599 for (uint32_t z = 0; z < numZSlices; ++z) {
600 if (descriptor == nullptr) {
601 // Note that this creates a descriptor that's autoreleased so we
602 // don't use AcquireNSRef
603 descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
604 }
Austin Eng0d661982020-01-16 00:12:10 +0000605
Austin Engfd783ce2021-05-18 21:51:33 +0000606 [*descriptor colorAttachments][attachment].texture = GetMTLTexture();
607 [*descriptor colorAttachments][attachment].loadAction =
608 MTLLoadActionClear;
609 [*descriptor colorAttachments][attachment].storeAction =
610 MTLStoreActionStore;
611 [*descriptor colorAttachments][attachment].clearColor =
612 MTLClearColorMake(dClearColor, dClearColor, dClearColor,
613 dClearColor);
614 [*descriptor colorAttachments][attachment].level = level;
615 [*descriptor colorAttachments][attachment].slice = arrayLayer;
616 [*descriptor colorAttachments][attachment].depthPlane = z;
Austin Eng0d661982020-01-16 00:12:10 +0000617
Austin Engfd783ce2021-05-18 21:51:33 +0000618 attachment++;
Austin Eng0d661982020-01-16 00:12:10 +0000619
Austin Engfd783ce2021-05-18 21:51:33 +0000620 if (attachment == kMaxColorAttachments) {
621 attachment = 0;
622 commandContext->BeginRender(descriptor.Get());
623 commandContext->EndRender();
624 descriptor = nullptr;
625 }
Austin Eng0d661982020-01-16 00:12:10 +0000626 }
627 }
Austin Eng0d661982020-01-16 00:12:10 +0000628
Corentin Wallez0055d952020-11-16 23:07:56 +0000629 if (descriptor != nullptr) {
630 commandContext->BeginRender(descriptor.Get());
Corentin Wallezda6dccd2020-05-29 07:37:48 +0000631 commandContext->EndRender();
632 }
Austin Eng0d661982020-01-16 00:12:10 +0000633 }
634 }
635 } else {
Yunchao He5fafb492020-06-12 00:37:31 +0000636 Extent3D largestMipSize = GetMipLevelVirtualSize(range.baseMipLevel);
Austin Eng0d661982020-01-16 00:12:10 +0000637
638 // Encode a buffer to texture copy to clear each subresource.
Austin Eng2cf5a082020-08-06 17:00:29 +0000639 for (Aspect aspect : IterateEnumMask(range.aspects)) {
Austin Eng3cd8c432021-06-01 21:25:33 +0000640 // Compute the buffer size big enough to fill the largest mip.
641 const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(aspect).block;
642
643 // Metal validation layers: sourceBytesPerRow must be at least 64.
644 uint32_t largestMipBytesPerRow =
645 std::max((largestMipSize.width / blockInfo.width) * blockInfo.byteSize, 64u);
646
647 // Metal validation layers: sourceBytesPerImage must be at least 512.
648 uint64_t largestMipBytesPerImage =
649 std::max(static_cast<uint64_t>(largestMipBytesPerRow) *
650 (largestMipSize.height / blockInfo.height),
651 512llu);
652
653 uint64_t bufferSize = largestMipBytesPerImage * largestMipSize.depthOrArrayLayers;
654
655 if (bufferSize > std::numeric_limits<NSUInteger>::max()) {
656 return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
657 }
658
659 DynamicUploader* uploader = device->GetDynamicUploader();
660 UploadHandle uploadHandle;
661 DAWN_TRY_ASSIGN(uploadHandle,
662 uploader->Allocate(bufferSize, device->GetPendingCommandSerial(),
663 blockInfo.byteSize));
664 memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
665
666 id<MTLBuffer> uploadBuffer =
667 ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle();
668
Austin Eng2cf5a082020-08-06 17:00:29 +0000669 for (uint32_t level = range.baseMipLevel;
670 level < range.baseMipLevel + range.levelCount; ++level) {
671 Extent3D virtualSize = GetMipLevelVirtualSize(level);
Austin Eng0d661982020-01-16 00:12:10 +0000672
Austin Eng2cf5a082020-08-06 17:00:29 +0000673 for (uint32_t arrayLayer = range.baseArrayLayer;
674 arrayLayer < range.baseArrayLayer + range.layerCount; ++arrayLayer) {
675 if (clearValue == TextureBase::ClearValue::Zero &&
676 IsSubresourceContentInitialized(
677 SubresourceRange::SingleMipAndLayer(level, arrayLayer, aspect))) {
678 // Skip lazy clears if already initialized.
679 continue;
680 }
Austin Eng0d661982020-01-16 00:12:10 +0000681
Austin Eng2cf5a082020-08-06 17:00:29 +0000682 MTLBlitOption blitOption = ComputeMTLBlitOption(GetFormat(), aspect);
Austin Eng3cd8c432021-06-01 21:25:33 +0000683 [commandContext->EnsureBlit()
684 copyFromBuffer:uploadBuffer
Austin Eng0d661982020-01-16 00:12:10 +0000685 sourceOffset:uploadHandle.startOffset
686 sourceBytesPerRow:largestMipBytesPerRow
687 sourceBytesPerImage:largestMipBytesPerImage
688 sourceSize:MTLSizeMake(virtualSize.width, virtualSize.height,
Austin Engfd783ce2021-05-18 21:51:33 +0000689 virtualSize.depthOrArrayLayers)
Austin Eng0d661982020-01-16 00:12:10 +0000690 toTexture:GetMTLTexture()
691 destinationSlice:arrayLayer
692 destinationLevel:level
693 destinationOrigin:MTLOriginMake(0, 0, 0)
Austin Eng2cf5a082020-08-06 17:00:29 +0000694 options:blitOption];
Austin Eng0d661982020-01-16 00:12:10 +0000695 }
696 }
697 }
698 }
699
700 if (clearValue == TextureBase::ClearValue::Zero) {
Yunchao He5fafb492020-06-12 00:37:31 +0000701 SetIsSubresourceContentInitialized(true, range);
Austin Eng0d661982020-01-16 00:12:10 +0000702 device->IncrementLazyClearCountForTesting();
703 }
704 return {};
705 }
706
Austin Eng26468c42021-05-08 16:01:16 +0000707 void Texture::EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
708 const SubresourceRange& range) {
Austin Eng0d661982020-01-16 00:12:10 +0000709 if (!GetDevice()->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse)) {
710 return;
711 }
Yunchao He5fafb492020-06-12 00:37:31 +0000712 if (!IsSubresourceContentInitialized(range)) {
Austin Eng0d661982020-01-16 00:12:10 +0000713 // If subresource has not been initialized, clear it to black as it could
714 // contain dirty bits from recycled memory
Austin Eng26468c42021-05-08 16:01:16 +0000715 GetDevice()->ConsumedError(
716 ClearTexture(commandContext, range, TextureBase::ClearValue::Zero));
Austin Eng0d661982020-01-16 00:12:10 +0000717 }
718 }
719
Corentin Wallez50f99582021-03-31 18:36:32 +0000720 // static
721 ResultOrError<Ref<TextureView>> TextureView::Create(TextureBase* texture,
722 const TextureViewDescriptor* descriptor) {
Corentin Wallez03f94372021-07-21 09:34:28 +0000723 Ref<TextureView> view = AcquireRef(new TextureView(texture, descriptor));
724 DAWN_TRY(view->Initialize(descriptor));
725 return view;
Corentin Wallez50f99582021-03-31 18:36:32 +0000726 }
727
Corentin Wallez03f94372021-07-21 09:34:28 +0000728 MaybeError TextureView::Initialize(const TextureViewDescriptor* descriptor) {
729 Texture* texture = ToBackend(GetTexture());
Austin Engda3c5ef2021-07-29 21:49:47 +0000730
731 // Texture could be destroyed by the time we make a view.
732 if (GetTexture()->GetTextureState() == Texture::TextureState::Destroyed) {
733 return {};
734 }
735
Corentin Wallez03f94372021-07-21 09:34:28 +0000736 id<MTLTexture> mtlTexture = texture->GetMTLTexture();
Jiawei Shao5dee56f2018-12-29 10:47:28 +0000737
Austin Eng0eff5982021-07-27 19:59:58 +0000738 if (!UsageNeedsTextureView(texture->GetInternalUsage())) {
Corentin Wallez0055d952020-11-16 23:07:56 +0000739 mMtlTextureView = nullptr;
Jiawei Shao5dee56f2018-12-29 10:47:28 +0000740 } else if (!RequiresCreatingNewTextureView(texture, descriptor)) {
Corentin Wallez0055d952020-11-16 23:07:56 +0000741 mMtlTextureView = mtlTexture;
Jiawei Shao5dee56f2018-12-29 10:47:28 +0000742 } else {
743 MTLPixelFormat format = MetalPixelFormat(descriptor->format);
Austin Enga0f17252020-11-04 15:27:11 +0000744 if (descriptor->aspect == wgpu::TextureAspect::StencilOnly) {
745 if (@available(macOS 10.12, iOS 10.0, *)) {
746 ASSERT(format == MTLPixelFormatDepth32Float_Stencil8);
747 format = MTLPixelFormatX32_Stencil8;
748 } else {
749 // TODO(enga): Add a workaround to back combined depth/stencil textures
750 // with Sampled usage using two separate textures.
751 // Or, consider always using the workaround for D32S8.
752 GetDevice()->ConsumedError(
753 DAWN_DEVICE_LOST_ERROR("Cannot create stencil-only texture view of "
754 "combined depth/stencil format."));
755 }
756 }
757
Jiawei Shao865cad82019-04-09 08:04:59 +0000758 MTLTextureType textureViewType =
759 MetalTextureViewType(descriptor->dimension, texture->GetSampleCount());
Jiawei Shao20301662019-02-21 00:45:19 +0000760 auto mipLevelRange = NSMakeRange(descriptor->baseMipLevel, descriptor->mipLevelCount);
761 auto arrayLayerRange =
762 NSMakeRange(descriptor->baseArrayLayer, descriptor->arrayLayerCount);
Jiawei Shao5dee56f2018-12-29 10:47:28 +0000763
Corentin Wallez0055d952020-11-16 23:07:56 +0000764 mMtlTextureView =
765 AcquireNSPRef([mtlTexture newTextureViewWithPixelFormat:format
Jiawei Shao5dee56f2018-12-29 10:47:28 +0000766 textureType:textureViewType
767 levels:mipLevelRange
Corentin Wallez0055d952020-11-16 23:07:56 +0000768 slices:arrayLayerRange]);
Corentin Wallez03f94372021-07-21 09:34:28 +0000769 if (mMtlTextureView == nil) {
770 return DAWN_INTERNAL_ERROR("Failed to create MTLTexture view.");
771 }
Jiawei Shao5dee56f2018-12-29 10:47:28 +0000772 }
Corentin Wallez03f94372021-07-21 09:34:28 +0000773
774 return {};
Corentin Wallez0ba55502017-06-14 15:46:59 -0400775 }
Corentin Wallezf58d84d2017-11-24 14:12:44 -0500776
Jiawei Shaoe8d12b42018-10-26 06:29:38 +0000777 id<MTLTexture> TextureView::GetMTLTexture() {
Corentin Wallez0055d952020-11-16 23:07:56 +0000778 ASSERT(mMtlTextureView != nullptr);
779 return mMtlTextureView.Get();
Jiawei Shaoe8d12b42018-10-26 06:29:38 +0000780 }
Corentin Wallez49a65d02018-07-24 16:45:45 +0200781}} // namespace dawn_native::metal