1 // Copyright 2020 The Dawn Authors 2 // 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 15 #include "utils/TestUtils.h" 16 17 #include "common/Assert.h" 18 #include "common/Constants.h" 19 #include "common/Math.h" 20 #include "utils/TextureUtils.h" 21 #include "utils/WGPUHelpers.h" 22 23 #include <vector> 24 25 namespace utils { 26 GetMinimumBytesPerRow(wgpu::TextureFormat format,uint32_t width)27 uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width) { 28 const uint32_t bytesPerBlock = utils::GetTexelBlockSizeInBytes(format); 29 const uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format); 30 ASSERT(width % blockWidth == 0); 31 return Align(bytesPerBlock * (width / blockWidth), kTextureBytesPerRowAlignment); 32 } 33 GetTextureDataCopyLayoutForTextureAtLevel(wgpu::TextureFormat format,wgpu::Extent3D textureSizeAtLevel0,uint32_t mipmapLevel,wgpu::TextureDimension dimension,uint32_t rowsPerImage)34 TextureDataCopyLayout GetTextureDataCopyLayoutForTextureAtLevel( 35 wgpu::TextureFormat format, 36 wgpu::Extent3D textureSizeAtLevel0, 37 uint32_t mipmapLevel, 38 wgpu::TextureDimension dimension, 39 uint32_t rowsPerImage) { 40 // Compressed texture formats not supported in this function yet. 41 ASSERT(utils::GetTextureFormatBlockWidth(format) == 1); 42 43 TextureDataCopyLayout layout; 44 45 layout.mipSize = {std::max(textureSizeAtLevel0.width >> mipmapLevel, 1u), 46 std::max(textureSizeAtLevel0.height >> mipmapLevel, 1u), 47 textureSizeAtLevel0.depthOrArrayLayers}; 48 49 if (dimension == wgpu::TextureDimension::e3D) { 50 layout.mipSize.depthOrArrayLayers = 51 std::max(textureSizeAtLevel0.depthOrArrayLayers >> mipmapLevel, 1u); 52 } 53 54 layout.bytesPerRow = GetMinimumBytesPerRow(format, layout.mipSize.width); 55 56 if (rowsPerImage == wgpu::kCopyStrideUndefined) { 57 rowsPerImage = layout.mipSize.height; 58 } 59 layout.rowsPerImage = rowsPerImage; 60 61 uint32_t appliedRowsPerImage = rowsPerImage > 0 ? rowsPerImage : layout.mipSize.height; 62 layout.bytesPerImage = layout.bytesPerRow * appliedRowsPerImage; 63 64 layout.byteLength = 65 RequiredBytesInCopy(layout.bytesPerRow, appliedRowsPerImage, layout.mipSize, format); 66 67 const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format); 68 layout.texelBlocksPerRow = layout.bytesPerRow / bytesPerTexel; 69 layout.texelBlocksPerImage = layout.bytesPerImage / bytesPerTexel; 70 layout.texelBlockCount = layout.byteLength / bytesPerTexel; 71 72 return layout; 73 } 74 RequiredBytesInCopy(uint64_t bytesPerRow,uint64_t rowsPerImage,wgpu::Extent3D copyExtent,wgpu::TextureFormat textureFormat)75 uint64_t RequiredBytesInCopy(uint64_t bytesPerRow, 76 uint64_t rowsPerImage, 77 wgpu::Extent3D copyExtent, 78 wgpu::TextureFormat textureFormat) { 79 uint32_t blockSize = utils::GetTexelBlockSizeInBytes(textureFormat); 80 uint32_t blockWidth = utils::GetTextureFormatBlockWidth(textureFormat); 81 uint32_t blockHeight = utils::GetTextureFormatBlockHeight(textureFormat); 82 ASSERT(copyExtent.width % blockWidth == 0); 83 uint32_t widthInBlocks = copyExtent.width / blockWidth; 84 ASSERT(copyExtent.height % blockHeight == 0); 85 uint32_t heightInBlocks = copyExtent.height / blockHeight; 86 return RequiredBytesInCopy(bytesPerRow, rowsPerImage, widthInBlocks, heightInBlocks, 87 copyExtent.depthOrArrayLayers, blockSize); 88 } 89 RequiredBytesInCopy(uint64_t bytesPerRow,uint64_t rowsPerImage,uint64_t widthInBlocks,uint64_t heightInBlocks,uint64_t depth,uint64_t bytesPerBlock)90 uint64_t RequiredBytesInCopy(uint64_t bytesPerRow, 91 uint64_t rowsPerImage, 92 uint64_t widthInBlocks, 93 uint64_t heightInBlocks, 94 uint64_t depth, 95 uint64_t bytesPerBlock) { 96 if (depth == 0) { 97 return 0; 98 } 99 100 uint64_t bytesPerImage = bytesPerRow * rowsPerImage; 101 uint64_t requiredBytesInCopy = bytesPerImage * (depth - 1); 102 if (heightInBlocks != 0) { 103 uint64_t lastRowBytes = widthInBlocks * bytesPerBlock; 104 uint64_t lastImageBytes = bytesPerRow * (heightInBlocks - 1) + lastRowBytes; 105 requiredBytesInCopy += lastImageBytes; 106 } 107 return requiredBytesInCopy; 108 } 109 GetTexelCountInCopyRegion(uint64_t bytesPerRow,uint64_t rowsPerImage,wgpu::Extent3D copyExtent,wgpu::TextureFormat textureFormat)110 uint64_t GetTexelCountInCopyRegion(uint64_t bytesPerRow, 111 uint64_t rowsPerImage, 112 wgpu::Extent3D copyExtent, 113 wgpu::TextureFormat textureFormat) { 114 return RequiredBytesInCopy(bytesPerRow, rowsPerImage, copyExtent, textureFormat) / 115 utils::GetTexelBlockSizeInBytes(textureFormat); 116 } 117 UnalignDynamicUploader(wgpu::Device device)118 void UnalignDynamicUploader(wgpu::Device device) { 119 std::vector<uint8_t> data = {1}; 120 121 wgpu::TextureDescriptor descriptor = {}; 122 descriptor.size = {1, 1, 1}; 123 descriptor.format = wgpu::TextureFormat::R8Unorm; 124 descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc; 125 wgpu::Texture texture = device.CreateTexture(&descriptor); 126 127 wgpu::ImageCopyTexture imageCopyTexture = 128 utils::CreateImageCopyTexture(texture, 0, {0, 0, 0}); 129 wgpu::TextureDataLayout textureDataLayout = 130 utils::CreateTextureDataLayout(0, wgpu::kCopyStrideUndefined); 131 wgpu::Extent3D copyExtent = {1, 1, 1}; 132 133 // WriteTexture with exactly 1 byte of data. 134 device.GetQueue().WriteTexture(&imageCopyTexture, data.data(), 1, &textureDataLayout, 135 ©Extent); 136 } 137 VertexFormatSize(wgpu::VertexFormat format)138 uint32_t VertexFormatSize(wgpu::VertexFormat format) { 139 switch (format) { 140 case wgpu::VertexFormat::Uint8x2: 141 case wgpu::VertexFormat::Sint8x2: 142 case wgpu::VertexFormat::Unorm8x2: 143 case wgpu::VertexFormat::Snorm8x2: 144 return 2; 145 case wgpu::VertexFormat::Uint8x4: 146 case wgpu::VertexFormat::Sint8x4: 147 case wgpu::VertexFormat::Unorm8x4: 148 case wgpu::VertexFormat::Snorm8x4: 149 case wgpu::VertexFormat::Uint16x2: 150 case wgpu::VertexFormat::Sint16x2: 151 case wgpu::VertexFormat::Unorm16x2: 152 case wgpu::VertexFormat::Snorm16x2: 153 case wgpu::VertexFormat::Float16x2: 154 case wgpu::VertexFormat::Float32: 155 case wgpu::VertexFormat::Uint32: 156 case wgpu::VertexFormat::Sint32: 157 return 4; 158 case wgpu::VertexFormat::Uint16x4: 159 case wgpu::VertexFormat::Sint16x4: 160 case wgpu::VertexFormat::Unorm16x4: 161 case wgpu::VertexFormat::Snorm16x4: 162 case wgpu::VertexFormat::Float16x4: 163 case wgpu::VertexFormat::Float32x2: 164 case wgpu::VertexFormat::Uint32x2: 165 case wgpu::VertexFormat::Sint32x2: 166 return 8; 167 case wgpu::VertexFormat::Float32x3: 168 case wgpu::VertexFormat::Uint32x3: 169 case wgpu::VertexFormat::Sint32x3: 170 return 12; 171 case wgpu::VertexFormat::Float32x4: 172 case wgpu::VertexFormat::Uint32x4: 173 case wgpu::VertexFormat::Sint32x4: 174 return 16; 175 case wgpu::VertexFormat::Undefined: 176 break; 177 } 178 UNREACHABLE(); 179 } 180 181 } // namespace utils 182