blob: 6e316c567d18bbd5f0eabc34229a4578c23c2ac9 [file] [log] [blame]
Yan, Shaobo93158eb2019-01-04 04:56:08 +00001// Copyright 2019 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 "dawn_native/vulkan/UtilsVulkan.h"
16
17#include "common/Assert.h"
Austin Eng2cf5a082020-08-06 17:00:29 +000018#include "dawn_native/EnumMaskIterator.h"
Natasha Lee5f8a8aa2019-08-14 23:11:42 +000019#include "dawn_native/Format.h"
shrekshaoe99ad762021-09-28 20:15:52 +000020#include "dawn_native/Pipeline.h"
21#include "dawn_native/ShaderModule.h"
Brandon Jonesc95e5742021-08-19 20:47:28 +000022#include "dawn_native/vulkan/DeviceVk.h"
Natasha Lee5f8a8aa2019-08-14 23:11:42 +000023#include "dawn_native/vulkan/Forward.h"
24#include "dawn_native/vulkan/TextureVk.h"
Brandon Jonesc95e5742021-08-19 20:47:28 +000025#include "dawn_native/vulkan/VulkanError.h"
Yan, Shaobo93158eb2019-01-04 04:56:08 +000026
27namespace dawn_native { namespace vulkan {
28
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000029 VkCompareOp ToVulkanCompareOp(wgpu::CompareFunction op) {
Yan, Shaobo93158eb2019-01-04 04:56:08 +000030 switch (op) {
Austin Engd6a54312020-04-17 19:32:07 +000031 case wgpu::CompareFunction::Never:
32 return VK_COMPARE_OP_NEVER;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000033 case wgpu::CompareFunction::Less:
Yan, Shaobo93158eb2019-01-04 04:56:08 +000034 return VK_COMPARE_OP_LESS;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000035 case wgpu::CompareFunction::LessEqual:
Yan, Shaobo93158eb2019-01-04 04:56:08 +000036 return VK_COMPARE_OP_LESS_OR_EQUAL;
Austin Engd6a54312020-04-17 19:32:07 +000037 case wgpu::CompareFunction::Greater:
38 return VK_COMPARE_OP_GREATER;
39 case wgpu::CompareFunction::GreaterEqual:
40 return VK_COMPARE_OP_GREATER_OR_EQUAL;
41 case wgpu::CompareFunction::Equal:
42 return VK_COMPARE_OP_EQUAL;
Corentin Wallez1f6c8c42019-10-23 11:57:41 +000043 case wgpu::CompareFunction::NotEqual:
Yan, Shaobo93158eb2019-01-04 04:56:08 +000044 return VK_COMPARE_OP_NOT_EQUAL;
Austin Engd6a54312020-04-17 19:32:07 +000045 case wgpu::CompareFunction::Always:
46 return VK_COMPARE_OP_ALWAYS;
Corentin Wallezeec9edf2020-09-24 14:56:50 +000047
48 case wgpu::CompareFunction::Undefined:
Ben Clayton999cc242021-09-23 17:34:53 +000049 break;
Yan, Shaobo93158eb2019-01-04 04:56:08 +000050 }
Ben Clayton999cc242021-09-23 17:34:53 +000051 UNREACHABLE();
Yan, Shaobo93158eb2019-01-04 04:56:08 +000052 }
53
Austin Eng2cf5a082020-08-06 17:00:29 +000054 // Convert Dawn texture aspects to Vulkan texture aspect flags
55 VkImageAspectFlags VulkanAspectMask(const Aspect& aspects) {
56 VkImageAspectFlags flags = 0;
57 for (Aspect aspect : IterateEnumMask(aspects)) {
58 switch (aspect) {
59 case Aspect::Color:
60 flags |= VK_IMAGE_ASPECT_COLOR_BIT;
61 break;
62 case Aspect::Depth:
63 flags |= VK_IMAGE_ASPECT_DEPTH_BIT;
64 break;
65 case Aspect::Stencil:
66 flags |= VK_IMAGE_ASPECT_STENCIL_BIT;
67 break;
Corentin Wallezef869c22021-01-21 11:07:44 +000068
69 case Aspect::CombinedDepthStencil:
70 flags |= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
71 break;
72
Bryan Bernhart14a23982021-02-05 20:11:24 +000073 case Aspect::Plane0:
74 case Aspect::Plane1:
Corentin Wallezeec9edf2020-09-24 14:56:50 +000075 case Aspect::None:
Austin Eng2cf5a082020-08-06 17:00:29 +000076 UNREACHABLE();
Austin Eng2cf5a082020-08-06 17:00:29 +000077 }
78 }
79 return flags;
80 }
81
Natasha Lee5f8a8aa2019-08-14 23:11:42 +000082 // Vulkan SPEC requires the source/destination region specified by each element of
83 // pRegions must be a region that is contained within srcImage/dstImage. Here the size of
84 // the image refers to the virtual size, while Dawn validates texture copy extent with the
85 // physical size, so we need to re-calculate the texture copy extent to ensure it should fit
86 // in the virtual size of the subresource.
87 Extent3D ComputeTextureCopyExtent(const TextureCopy& textureCopy, const Extent3D& copySize) {
88 Extent3D validTextureCopyExtent = copySize;
89 const TextureBase* texture = textureCopy.texture.Get();
90 Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(textureCopy.mipLevel);
Austin Eng00c999a2021-06-23 14:55:13 +000091 ASSERT(textureCopy.origin.x <= virtualSizeAtLevel.width);
92 ASSERT(textureCopy.origin.y <= virtualSizeAtLevel.height);
93 if (copySize.width > virtualSizeAtLevel.width - textureCopy.origin.x) {
Natasha Lee5f8a8aa2019-08-14 23:11:42 +000094 ASSERT(texture->GetFormat().isCompressed);
95 validTextureCopyExtent.width = virtualSizeAtLevel.width - textureCopy.origin.x;
96 }
Austin Eng00c999a2021-06-23 14:55:13 +000097 if (copySize.height > virtualSizeAtLevel.height - textureCopy.origin.y) {
Natasha Lee5f8a8aa2019-08-14 23:11:42 +000098 ASSERT(texture->GetFormat().isCompressed);
99 validTextureCopyExtent.height = virtualSizeAtLevel.height - textureCopy.origin.y;
100 }
101
102 return validTextureCopyExtent;
103 }
104
105 VkBufferImageCopy ComputeBufferImageCopyRegion(const BufferCopy& bufferCopy,
106 const TextureCopy& textureCopy,
107 const Extent3D& copySize) {
Tomek Ponitkae28cc552020-07-16 09:08:41 +0000108 TextureDataLayout passDataLayout;
109 passDataLayout.offset = bufferCopy.offset;
110 passDataLayout.rowsPerImage = bufferCopy.rowsPerImage;
111 passDataLayout.bytesPerRow = bufferCopy.bytesPerRow;
112 return ComputeBufferImageCopyRegion(passDataLayout, textureCopy, copySize);
113 }
114
115 VkBufferImageCopy ComputeBufferImageCopyRegion(const TextureDataLayout& dataLayout,
116 const TextureCopy& textureCopy,
117 const Extent3D& copySize) {
Natasha Lee5f8a8aa2019-08-14 23:11:42 +0000118 const Texture* texture = ToBackend(textureCopy.texture.Get());
119
120 VkBufferImageCopy region;
121
Tomek Ponitkae28cc552020-07-16 09:08:41 +0000122 region.bufferOffset = dataLayout.offset;
Natasha Lee5f8a8aa2019-08-14 23:11:42 +0000123 // In Vulkan the row length is in texels while it is in bytes for Dawn
Austin Eng0a434272020-08-04 19:46:37 +0000124 const TexelBlockInfo& blockInfo =
Corentin Wallez6298d2b2020-10-15 09:05:03 +0000125 texture->GetFormat().GetAspectInfo(textureCopy.aspect).block;
126 ASSERT(dataLayout.bytesPerRow % blockInfo.byteSize == 0);
127 region.bufferRowLength = dataLayout.bytesPerRow / blockInfo.byteSize * blockInfo.width;
128 region.bufferImageHeight = dataLayout.rowsPerImage * blockInfo.height;
Natasha Lee5f8a8aa2019-08-14 23:11:42 +0000129
Austin Eng2cf5a082020-08-06 17:00:29 +0000130 region.imageSubresource.aspectMask = VulkanAspectMask(textureCopy.aspect);
Natasha Lee5f8a8aa2019-08-14 23:11:42 +0000131 region.imageSubresource.mipLevel = textureCopy.mipLevel;
Natasha Lee5f8a8aa2019-08-14 23:11:42 +0000132
Corentin Wallezff905992020-06-26 11:07:00 +0000133 switch (textureCopy.texture->GetDimension()) {
134 case wgpu::TextureDimension::e2D: {
135 region.imageOffset.x = textureCopy.origin.x;
136 region.imageOffset.y = textureCopy.origin.y;
137 region.imageOffset.z = 0;
Natasha Lee5f8a8aa2019-08-14 23:11:42 +0000138
Corentin Wallezff905992020-06-26 11:07:00 +0000139 region.imageSubresource.baseArrayLayer = textureCopy.origin.z;
shrekshaob00de7f2021-03-22 21:12:36 +0000140 region.imageSubresource.layerCount = copySize.depthOrArrayLayers;
Jiawei Shao92379bf2020-06-21 09:33:44 +0000141
Corentin Wallezff905992020-06-26 11:07:00 +0000142 Extent3D imageExtent = ComputeTextureCopyExtent(textureCopy, copySize);
143 region.imageExtent.width = imageExtent.width;
144 region.imageExtent.height = imageExtent.height;
145 region.imageExtent.depth = 1;
146 break;
147 }
148
Austin Engd066d172021-05-10 18:58:51 +0000149 case wgpu::TextureDimension::e3D: {
150 region.imageOffset.x = textureCopy.origin.x;
151 region.imageOffset.y = textureCopy.origin.y;
152 region.imageOffset.z = textureCopy.origin.z;
153
154 region.imageSubresource.baseArrayLayer = 0;
155 region.imageSubresource.layerCount = 1;
156
157 Extent3D imageExtent = ComputeTextureCopyExtent(textureCopy, copySize);
158 region.imageExtent.width = imageExtent.width;
159 region.imageExtent.height = imageExtent.height;
160 region.imageExtent.depth = imageExtent.depthOrArrayLayers;
161 break;
162 }
163
Corentin Wallezeec9edf2020-09-24 14:56:50 +0000164 case wgpu::TextureDimension::e1D:
Corentin Wallezff905992020-06-26 11:07:00 +0000165 UNREACHABLE();
Corentin Wallezff905992020-06-26 11:07:00 +0000166 }
Natasha Lee5f8a8aa2019-08-14 23:11:42 +0000167
168 return region;
169 }
Brandon Jonesc95e5742021-08-19 20:47:28 +0000170
171 void SetDebugName(Device* device,
172 VkObjectType objectType,
173 uint64_t objectHandle,
174 const char* prefix,
175 std::string label) {
Brandon Jones8a0b49b2021-09-02 21:15:40 +0000176 if (!objectHandle) {
177 return;
178 }
179
Brandon Jonesc95e5742021-08-19 20:47:28 +0000180 if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
181 VkDebugUtilsObjectNameInfoEXT objectNameInfo;
182 objectNameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
183 objectNameInfo.pNext = nullptr;
184 objectNameInfo.objectType = objectType;
185 objectNameInfo.objectHandle = objectHandle;
186
187 if (label.empty() || !device->IsToggleEnabled(Toggle::UseUserDefinedLabelsInBackend)) {
188 objectNameInfo.pObjectName = prefix;
189 device->fn.SetDebugUtilsObjectNameEXT(device->GetVkDevice(), &objectNameInfo);
190 return;
191 }
192
193 std::string objectName = prefix;
194 objectName += "_";
195 objectName += label;
196 objectNameInfo.pObjectName = objectName.c_str();
197 device->fn.SetDebugUtilsObjectNameEXT(device->GetVkDevice(), &objectNameInfo);
198 }
199 }
shrekshaoe99ad762021-09-28 20:15:52 +0000200
201 VkSpecializationInfo* GetVkSpecializationInfo(
202 const ProgrammableStage& programmableStage,
203 VkSpecializationInfo* specializationInfo,
Shrek Shaob0a5ed42021-11-04 18:43:10 +0000204 std::vector<OverridableConstantScalar>* specializationDataEntries,
shrekshaoe99ad762021-09-28 20:15:52 +0000205 std::vector<VkSpecializationMapEntry>* specializationMapEntries) {
206 ASSERT(specializationInfo);
207 ASSERT(specializationDataEntries);
208 ASSERT(specializationMapEntries);
209
210 if (programmableStage.constants.size() == 0) {
211 return nullptr;
212 }
213
214 const EntryPointMetadata& entryPointMetaData =
215 programmableStage.module->GetEntryPoint(programmableStage.entryPoint);
216
217 for (const auto& pipelineConstant : programmableStage.constants) {
Shrek Shao5e2e2d82021-10-28 00:04:07 +0000218 const std::string& identifier = pipelineConstant.first;
shrekshaoe99ad762021-09-28 20:15:52 +0000219 double value = pipelineConstant.second;
220
Shrek Shao5e2e2d82021-10-28 00:04:07 +0000221 // This is already validated so `identifier` must exist
222 const auto& moduleConstant = entryPointMetaData.overridableConstants.at(identifier);
shrekshaoe99ad762021-09-28 20:15:52 +0000223
224 specializationMapEntries->push_back(
225 VkSpecializationMapEntry{moduleConstant.id,
226 static_cast<uint32_t>(specializationDataEntries->size() *
Shrek Shaob0a5ed42021-11-04 18:43:10 +0000227 sizeof(OverridableConstantScalar)),
228 sizeof(OverridableConstantScalar)});
shrekshaoe99ad762021-09-28 20:15:52 +0000229
Shrek Shaob0a5ed42021-11-04 18:43:10 +0000230 OverridableConstantScalar entry{};
shrekshaoe99ad762021-09-28 20:15:52 +0000231 switch (moduleConstant.type) {
232 case EntryPointMetadata::OverridableConstant::Type::Boolean:
Shrek Shao5e2e2d82021-10-28 00:04:07 +0000233 entry.b = static_cast<int32_t>(value);
shrekshaoe99ad762021-09-28 20:15:52 +0000234 break;
235 case EntryPointMetadata::OverridableConstant::Type::Float32:
236 entry.f32 = static_cast<float>(value);
237 break;
238 case EntryPointMetadata::OverridableConstant::Type::Int32:
239 entry.i32 = static_cast<int32_t>(value);
240 break;
241 case EntryPointMetadata::OverridableConstant::Type::Uint32:
242 entry.u32 = static_cast<uint32_t>(value);
243 break;
244 default:
245 UNREACHABLE();
246 }
247 specializationDataEntries->push_back(entry);
248 }
249
250 specializationInfo->mapEntryCount = static_cast<uint32_t>(specializationMapEntries->size());
251 specializationInfo->pMapEntries = specializationMapEntries->data();
252 specializationInfo->dataSize =
Shrek Shaob0a5ed42021-11-04 18:43:10 +0000253 specializationDataEntries->size() * sizeof(OverridableConstantScalar);
shrekshaoe99ad762021-09-28 20:15:52 +0000254 specializationInfo->pData = specializationDataEntries->data();
255
256 return specializationInfo;
257 }
258
Austin Eng0a434272020-08-04 19:46:37 +0000259}} // namespace dawn_native::vulkan