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