• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                                        &copyExtent);
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