1 // Copyright 2017 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/DawnHelpers.h" 16 17 #include "common/Assert.h" 18 #include "common/Constants.h" 19 20 #include <shaderc/shaderc.hpp> 21 22 #include <cstring> 23 #include <iomanip> 24 #include <iostream> 25 #include <sstream> 26 27 namespace utils { 28 29 namespace { 30 ShadercShaderKind(ShaderStage stage)31 shaderc_shader_kind ShadercShaderKind(ShaderStage stage) { 32 switch (stage) { 33 case ShaderStage::Vertex: 34 return shaderc_glsl_vertex_shader; 35 case ShaderStage::Fragment: 36 return shaderc_glsl_fragment_shader; 37 case ShaderStage::Compute: 38 return shaderc_glsl_compute_shader; 39 default: 40 UNREACHABLE(); 41 } 42 } 43 CreateShaderModuleFromResult(const dawn::Device & device,const shaderc::SpvCompilationResult & result)44 dawn::ShaderModule CreateShaderModuleFromResult( 45 const dawn::Device& device, 46 const shaderc::SpvCompilationResult& result) { 47 // result.cend and result.cbegin return pointers to uint32_t. 48 const uint32_t* resultBegin = result.cbegin(); 49 const uint32_t* resultEnd = result.cend(); 50 // So this size is in units of sizeof(uint32_t). 51 ptrdiff_t resultSize = resultEnd - resultBegin; 52 // SetSource takes data as uint32_t*. 53 54 dawn::ShaderModuleDescriptor descriptor; 55 descriptor.codeSize = static_cast<uint32_t>(resultSize); 56 descriptor.code = result.cbegin(); 57 return device.CreateShaderModule(&descriptor); 58 } 59 60 } // anonymous namespace 61 CreateShaderModule(const dawn::Device & device,ShaderStage stage,const char * source)62 dawn::ShaderModule CreateShaderModule(const dawn::Device& device, 63 ShaderStage stage, 64 const char* source) { 65 shaderc_shader_kind kind = ShadercShaderKind(stage); 66 67 shaderc::Compiler compiler; 68 auto result = compiler.CompileGlslToSpv(source, strlen(source), kind, "myshader?"); 69 if (result.GetCompilationStatus() != shaderc_compilation_status_success) { 70 std::cerr << result.GetErrorMessage(); 71 return {}; 72 } 73 #ifdef DUMP_SPIRV_ASSEMBLY 74 { 75 shaderc::CompileOptions options; 76 auto resultAsm = compiler.CompileGlslToSpvAssembly(source, strlen(source), kind, 77 "myshader?", options); 78 size_t sizeAsm = (resultAsm.cend() - resultAsm.cbegin()); 79 80 char* buffer = reinterpret_cast<char*>(malloc(sizeAsm + 1)); 81 memcpy(buffer, resultAsm.cbegin(), sizeAsm); 82 buffer[sizeAsm] = '\0'; 83 printf("SPIRV ASSEMBLY DUMP START\n%s\nSPIRV ASSEMBLY DUMP END\n", buffer); 84 free(buffer); 85 } 86 #endif 87 88 #ifdef DUMP_SPIRV_JS_ARRAY 89 printf("SPIRV JS ARRAY DUMP START\n"); 90 for (size_t i = 0; i < size; i++) { 91 printf("%#010x", result.cbegin()[i]); 92 if ((i + 1) % 4 == 0) { 93 printf(",\n"); 94 } else { 95 printf(", "); 96 } 97 } 98 printf("\n"); 99 printf("SPIRV JS ARRAY DUMP END\n"); 100 #endif 101 102 return CreateShaderModuleFromResult(device, result); 103 } 104 CreateShaderModuleFromASM(const dawn::Device & device,const char * source)105 dawn::ShaderModule CreateShaderModuleFromASM(const dawn::Device& device, const char* source) { 106 shaderc::Compiler compiler; 107 shaderc::SpvCompilationResult result = compiler.AssembleToSpv(source, strlen(source)); 108 if (result.GetCompilationStatus() != shaderc_compilation_status_success) { 109 std::cerr << result.GetErrorMessage(); 110 return {}; 111 } 112 113 return CreateShaderModuleFromResult(device, result); 114 } 115 CreateBufferFromData(const dawn::Device & device,const void * data,uint64_t size,dawn::BufferUsageBit usage)116 dawn::Buffer CreateBufferFromData(const dawn::Device& device, 117 const void* data, 118 uint64_t size, 119 dawn::BufferUsageBit usage) { 120 dawn::BufferDescriptor descriptor; 121 descriptor.size = size; 122 descriptor.usage = usage | dawn::BufferUsageBit::CopyDst; 123 124 dawn::Buffer buffer = device.CreateBuffer(&descriptor); 125 buffer.SetSubData(0, size, data); 126 return buffer; 127 } 128 ComboRenderPassDescriptor(std::initializer_list<dawn::TextureView> colorAttachmentInfo,dawn::TextureView depthStencil)129 ComboRenderPassDescriptor::ComboRenderPassDescriptor( 130 std::initializer_list<dawn::TextureView> colorAttachmentInfo, 131 dawn::TextureView depthStencil) 132 : cColorAttachmentsInfoPtr() { 133 for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { 134 mColorAttachmentsInfo[i].loadOp = dawn::LoadOp::Clear; 135 mColorAttachmentsInfo[i].storeOp = dawn::StoreOp::Store; 136 mColorAttachmentsInfo[i].clearColor = {0.0f, 0.0f, 0.0f, 0.0f}; 137 cColorAttachmentsInfoPtr[i] = nullptr; 138 } 139 140 cDepthStencilAttachmentInfo.clearDepth = 1.0f; 141 cDepthStencilAttachmentInfo.clearStencil = 0; 142 cDepthStencilAttachmentInfo.depthLoadOp = dawn::LoadOp::Clear; 143 cDepthStencilAttachmentInfo.depthStoreOp = dawn::StoreOp::Store; 144 cDepthStencilAttachmentInfo.stencilLoadOp = dawn::LoadOp::Clear; 145 cDepthStencilAttachmentInfo.stencilStoreOp = dawn::StoreOp::Store; 146 147 colorAttachmentCount = static_cast<uint32_t>(colorAttachmentInfo.size()); 148 uint32_t colorAttachmentIndex = 0; 149 for (const dawn::TextureView& colorAttachment : colorAttachmentInfo) { 150 if (colorAttachment.Get() != nullptr) { 151 mColorAttachmentsInfo[colorAttachmentIndex].attachment = colorAttachment; 152 cColorAttachmentsInfoPtr[colorAttachmentIndex] = 153 &mColorAttachmentsInfo[colorAttachmentIndex]; 154 } 155 ++colorAttachmentIndex; 156 } 157 colorAttachments = cColorAttachmentsInfoPtr; 158 159 if (depthStencil.Get() != nullptr) { 160 cDepthStencilAttachmentInfo.attachment = depthStencil; 161 depthStencilAttachment = &cDepthStencilAttachmentInfo; 162 } else { 163 depthStencilAttachment = nullptr; 164 } 165 } 166 operator =(const ComboRenderPassDescriptor & otherRenderPass)167 const ComboRenderPassDescriptor& ComboRenderPassDescriptor::operator=( 168 const ComboRenderPassDescriptor& otherRenderPass) { 169 cDepthStencilAttachmentInfo = otherRenderPass.cDepthStencilAttachmentInfo; 170 mColorAttachmentsInfo = otherRenderPass.mColorAttachmentsInfo; 171 172 colorAttachmentCount = otherRenderPass.colorAttachmentCount; 173 174 // Assign the pointers in colorAttachmentsInfoPtr to items in this->mColorAttachmentsInfo 175 for (uint32_t i = 0; i < colorAttachmentCount; ++i) { 176 if (otherRenderPass.cColorAttachmentsInfoPtr[i] != nullptr) { 177 cColorAttachmentsInfoPtr[i] = &mColorAttachmentsInfo[i]; 178 } else { 179 cColorAttachmentsInfoPtr[i] = nullptr; 180 } 181 } 182 colorAttachments = cColorAttachmentsInfoPtr; 183 184 if (otherRenderPass.depthStencilAttachment != nullptr) { 185 // Assign desc.depthStencilAttachment to this->depthStencilAttachmentInfo; 186 depthStencilAttachment = &cDepthStencilAttachmentInfo; 187 } else { 188 depthStencilAttachment = nullptr; 189 } 190 191 return *this; 192 } 193 BasicRenderPass()194 BasicRenderPass::BasicRenderPass() 195 : width(0), 196 height(0), 197 color(nullptr), 198 colorFormat(dawn::TextureFormat::RGBA8Unorm), 199 renderPassInfo({}) { 200 } 201 BasicRenderPass(uint32_t texWidth,uint32_t texHeight,dawn::Texture colorAttachment,dawn::TextureFormat textureFormat)202 BasicRenderPass::BasicRenderPass(uint32_t texWidth, 203 uint32_t texHeight, 204 dawn::Texture colorAttachment, 205 dawn::TextureFormat textureFormat) 206 : width(texWidth), 207 height(texHeight), 208 color(colorAttachment), 209 colorFormat(textureFormat), 210 renderPassInfo({colorAttachment.CreateDefaultView()}) { 211 } 212 CreateBasicRenderPass(const dawn::Device & device,uint32_t width,uint32_t height)213 BasicRenderPass CreateBasicRenderPass(const dawn::Device& device, 214 uint32_t width, 215 uint32_t height) { 216 DAWN_ASSERT(width > 0 && height > 0); 217 218 dawn::TextureDescriptor descriptor; 219 descriptor.dimension = dawn::TextureDimension::e2D; 220 descriptor.size.width = width; 221 descriptor.size.height = height; 222 descriptor.size.depth = 1; 223 descriptor.arrayLayerCount = 1; 224 descriptor.sampleCount = 1; 225 descriptor.format = BasicRenderPass::kDefaultColorFormat; 226 descriptor.mipLevelCount = 1; 227 descriptor.usage = dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::CopySrc; 228 dawn::Texture color = device.CreateTexture(&descriptor); 229 230 return BasicRenderPass(width, height, color); 231 } 232 CreateBufferCopyView(dawn::Buffer buffer,uint64_t offset,uint32_t rowPitch,uint32_t imageHeight)233 dawn::BufferCopyView CreateBufferCopyView(dawn::Buffer buffer, 234 uint64_t offset, 235 uint32_t rowPitch, 236 uint32_t imageHeight) { 237 dawn::BufferCopyView bufferCopyView; 238 bufferCopyView.buffer = buffer; 239 bufferCopyView.offset = offset; 240 bufferCopyView.rowPitch = rowPitch; 241 bufferCopyView.imageHeight = imageHeight; 242 243 return bufferCopyView; 244 } 245 CreateTextureCopyView(dawn::Texture texture,uint32_t mipLevel,uint32_t arrayLayer,dawn::Origin3D origin)246 dawn::TextureCopyView CreateTextureCopyView(dawn::Texture texture, 247 uint32_t mipLevel, 248 uint32_t arrayLayer, 249 dawn::Origin3D origin) { 250 dawn::TextureCopyView textureCopyView; 251 textureCopyView.texture = texture; 252 textureCopyView.mipLevel = mipLevel; 253 textureCopyView.arrayLayer = arrayLayer; 254 textureCopyView.origin = origin; 255 256 return textureCopyView; 257 } 258 GetDefaultSamplerDescriptor()259 dawn::SamplerDescriptor GetDefaultSamplerDescriptor() { 260 dawn::SamplerDescriptor desc; 261 262 desc.minFilter = dawn::FilterMode::Linear; 263 desc.magFilter = dawn::FilterMode::Linear; 264 desc.mipmapFilter = dawn::FilterMode::Linear; 265 desc.addressModeU = dawn::AddressMode::Repeat; 266 desc.addressModeV = dawn::AddressMode::Repeat; 267 desc.addressModeW = dawn::AddressMode::Repeat; 268 desc.lodMinClamp = kLodMin; 269 desc.lodMaxClamp = kLodMax; 270 desc.compare = dawn::CompareFunction::Never; 271 272 return desc; 273 } 274 MakeBasicPipelineLayout(const dawn::Device & device,const dawn::BindGroupLayout * bindGroupLayout)275 dawn::PipelineLayout MakeBasicPipelineLayout(const dawn::Device& device, 276 const dawn::BindGroupLayout* bindGroupLayout) { 277 dawn::PipelineLayoutDescriptor descriptor; 278 if (bindGroupLayout != nullptr) { 279 descriptor.bindGroupLayoutCount = 1; 280 descriptor.bindGroupLayouts = bindGroupLayout; 281 } else { 282 descriptor.bindGroupLayoutCount = 0; 283 descriptor.bindGroupLayouts = nullptr; 284 } 285 return device.CreatePipelineLayout(&descriptor); 286 } 287 MakeBindGroupLayout(const dawn::Device & device,std::initializer_list<dawn::BindGroupLayoutBinding> bindingsInitializer)288 dawn::BindGroupLayout MakeBindGroupLayout( 289 const dawn::Device& device, 290 std::initializer_list<dawn::BindGroupLayoutBinding> bindingsInitializer) { 291 constexpr dawn::ShaderStageBit kNoStages{}; 292 293 std::vector<dawn::BindGroupLayoutBinding> bindings; 294 for (const dawn::BindGroupLayoutBinding& binding : bindingsInitializer) { 295 if (binding.visibility != kNoStages) { 296 bindings.push_back(binding); 297 } 298 } 299 300 dawn::BindGroupLayoutDescriptor descriptor; 301 descriptor.bindingCount = static_cast<uint32_t>(bindings.size()); 302 descriptor.bindings = bindings.data(); 303 return device.CreateBindGroupLayout(&descriptor); 304 } 305 BindingInitializationHelper(uint32_t binding,const dawn::Sampler & sampler)306 BindingInitializationHelper::BindingInitializationHelper(uint32_t binding, 307 const dawn::Sampler& sampler) 308 : binding(binding), sampler(sampler) { 309 } 310 BindingInitializationHelper(uint32_t binding,const dawn::TextureView & textureView)311 BindingInitializationHelper::BindingInitializationHelper(uint32_t binding, 312 const dawn::TextureView& textureView) 313 : binding(binding), textureView(textureView) { 314 } 315 BindingInitializationHelper(uint32_t binding,const dawn::Buffer & buffer,uint64_t offset,uint64_t size)316 BindingInitializationHelper::BindingInitializationHelper(uint32_t binding, 317 const dawn::Buffer& buffer, 318 uint64_t offset, 319 uint64_t size) 320 : binding(binding), buffer(buffer), offset(offset), size(size) { 321 } 322 GetAsBinding() const323 dawn::BindGroupBinding BindingInitializationHelper::GetAsBinding() const { 324 dawn::BindGroupBinding result; 325 326 result.binding = binding; 327 result.sampler = sampler; 328 result.textureView = textureView; 329 result.buffer = buffer; 330 result.offset = offset; 331 result.size = size; 332 333 return result; 334 } 335 MakeBindGroup(const dawn::Device & device,const dawn::BindGroupLayout & layout,std::initializer_list<BindingInitializationHelper> bindingsInitializer)336 dawn::BindGroup MakeBindGroup( 337 const dawn::Device& device, 338 const dawn::BindGroupLayout& layout, 339 std::initializer_list<BindingInitializationHelper> bindingsInitializer) { 340 std::vector<dawn::BindGroupBinding> bindings; 341 for (const BindingInitializationHelper& helper : bindingsInitializer) { 342 bindings.push_back(helper.GetAsBinding()); 343 } 344 345 dawn::BindGroupDescriptor descriptor; 346 descriptor.layout = layout; 347 descriptor.bindingCount = bindings.size(); 348 descriptor.bindings = bindings.data(); 349 350 return device.CreateBindGroup(&descriptor); 351 } 352 353 } // namespace utils 354