From 9ea2b7a3207708d9f276d5a5d877acf5ff3b160e Mon Sep 17 00:00:00 2001 From: SarahM0 Date: Fri, 17 May 2019 11:16:33 -0400 Subject: [PATCH 1/7] initial commit - WIP --- src/dawn/engine_dawn.cc | 148 +++++++++++++++++++++++++++++- src/dawn/pipeline_info.h | 3 + tests/cases/draw_rectangles.amber | 3 +- 3 files changed, 149 insertions(+), 5 deletions(-) diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc index 7a6aea8ba..3683d61ed 100644 --- a/src/dawn/engine_dawn.cc +++ b/src/dawn/engine_dawn.cc @@ -355,6 +355,75 @@ ::dawn::SamplerDescriptor GetDefaultSamplerDescriptor() { return desc; } +// Creates a bind group. +// Copied from Dawn utils source code. + +// Helpers to make creating bind groups look nicer: +// +// utils::MakeBindGroup(device, layout, { +// {0, mySampler}, +// {1, myBuffer, offset, size}, +// {3, myTexture} +// }); + +// Structure with one constructor per-type of bindings, so that the +// initializer_list accepts bindings with the right type and no extra +// information. +struct BindingInitializationHelper { + BindingInitializationHelper(uint32_t binding, const ::dawn::Sampler& sampler); + BindingInitializationHelper(uint32_t binding, + const ::dawn::TextureView& textureView); + BindingInitializationHelper(uint32_t binding, + const ::dawn::Buffer& buffer, + uint64_t offset, + uint64_t size); + + ::dawn::BindGroupBinding GetAsBinding() const; + + uint32_t binding; + ::dawn::Sampler sampler; + ::dawn::TextureView textureView; + ::dawn::Buffer buffer; + uint64_t offset = 0; + uint64_t size = 0; +}; +BindingInitializationHelper::BindingInitializationHelper( + uint32_t binding, + const ::dawn::Buffer& buffer, + uint64_t offset, + uint64_t size) + : binding(binding), buffer(buffer), offset(offset), size(size) {} + +::dawn::BindGroupBinding BindingInitializationHelper::GetAsBinding() const { + ::dawn::BindGroupBinding result; + + result.binding = binding; + result.sampler = sampler; + result.textureView = textureView; + result.buffer = buffer; + result.offset = offset; + result.size = size; + + return result; +} + +::dawn::BindGroup MakeBindGroup( + const ::dawn::Device& device, + const ::dawn::BindGroupLayout& layout, + std::initializer_list bindingsInitializer) { + std::vector<::dawn::BindGroupBinding> bindings; + for (const BindingInitializationHelper& helper : bindingsInitializer) { + bindings.push_back(helper.GetAsBinding()); + } + + ::dawn::BindGroupDescriptor descriptor; + descriptor.layout = layout; + descriptor.bindingCount = bindings.size(); + descriptor.bindings = bindings.data(); + + return device.CreateBindGroup(&descriptor); +} + // Creates a bind group layout. // Copied from Dawn utils source code. ::dawn::BindGroupLayout MakeBindGroupLayout( @@ -659,7 +728,12 @@ Result DawnPipelineHelper::CreateRenderPipelineDescriptor( depth_stencil_format = ::dawn::TextureFormat::D32FloatS8Uint; } - renderPipelineDescriptor.layout = MakeBasicPipelineLayout(device, nullptr); + if (render_pipeline.hasBinding) + renderPipelineDescriptor.layout = + MakeBasicPipelineLayout(device, &render_pipeline.bindGroupLayout); + else + renderPipelineDescriptor.layout = MakeBasicPipelineLayout(device, nullptr); + renderPipelineDescriptor.primitiveTopology = ::dawn::PrimitiveTopology::TriangleList; renderPipelineDescriptor.sampleCount = 1; @@ -808,7 +882,7 @@ Result DawnPipelineHelper::CreateRenderPassDescriptor( Result EngineDawn::DoDrawRect(const DrawRectCommand* command) { RenderPipelineInfo* render_pipeline = GetRenderPipeline(command); if (!render_pipeline) - return Result("Clear invoked on invalid or missing render pipeline"); + return Result("DrawRect invoked on invalid or missing render pipeline"); Result result = CreateFramebufferIfNeeded(render_pipeline); if (!result.IsSuccess()) return result; @@ -876,6 +950,9 @@ Result EngineDawn::DoDrawRect(const DrawRectCommand* command) { pass.SetPipeline(pipeline); pass.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets); pass.SetIndexBuffer(indexBuffer, 0); + if (render_pipeline->hasBinding) { + pass.SetBindGroup(0, render_pipeline->bindGroup, 0, nullptr); + } pass.DrawIndexed(6, 1, 0, 0, 0); pass.EndPass(); @@ -905,8 +982,71 @@ Result EngineDawn::DoPatchParameterVertices( return Result("Dawn:DoPatch not implemented"); } -Result EngineDawn::DoBuffer(const BufferCommand*) { - return Result("Dawn:DoBuffer not implemented"); +// ::dawn::CommandBuffer CreateSimpleComputeCommandBuffer( +// const dawn::ComputePipeline& pipeline, const dawn::BindGroup& bindGroup) +// { +// dawn::CommandEncoder encoder = device.CreateCommandEncoder(); +// dawn::ComputePassEncoder pass = encoder.BeginComputePass(); +// pass.SetPipeline(pipeline); +// pass.SetBindGroup(0, bindGroup, 0, nullptr); +// pass.Dispatch(1, 1, 1); +// pass.EndPass(); +// return encoder.Finish(); +// } + +Result EngineDawn::DoBuffer(const BufferCommand* command) { + // TODO(SarahM0): it can be a compute pipeline too + RenderPipelineInfo* render_pipeline = GetRenderPipeline(command); + if (!render_pipeline) + return Result("DoBuffer invoked on invalid or missing render pipeline"); + Result result = CreateFramebufferIfNeeded(render_pipeline); + if (!result.IsSuccess()) + return result; + + if (!command->IsSSBO() && !command->IsUniform()) + return Result("EngineDawn::DoBuffer not supported buffer type"); + + const std::vector values = command->GetValues(); + std::vector fValues; + float* f = new float[values.size()]; + for (uint i = 0; i < values.size(); i++) + f[i] = values[i].AsFloat(); + + ::dawn::Buffer buffer; + if (command->IsSSBO()) + buffer = CreateBufferFromData(*device_, f, sizeof(f), + ::dawn::BufferUsageBit::Storage | + ::dawn::BufferUsageBit::TransferSrc | + ::dawn::BufferUsageBit::TransferDst); + else if (command->IsUniform()) + buffer = CreateBufferFromData(*device_, f, sizeof(f), + ::dawn::BufferUsageBit::Uniform | + ::dawn::BufferUsageBit::TransferSrc | + ::dawn::BufferUsageBit::TransferDst); + else + return Result("EngineDawn::DoBuffer not supported buffer type"); + + ::dawn::ShaderStageBit kAllStages = + ::dawn::ShaderStageBit::Vertex | ::dawn::ShaderStageBit::Fragment; + + render_pipeline->bindGroupLayout = MakeBindGroupLayout( + *device_, { + {0, kAllStages, ::dawn::BindingType::StorageBuffer}, + }); + + render_pipeline->hasBinding = true; + + render_pipeline->bindGroup = + MakeBindGroup(*device_, render_pipeline->bindGroupLayout, + { + { + command->GetBinding(), + buffer, + 0, + sizeof(f), + }, + }); + return {}; } Result EngineDawn::CreateFramebufferIfNeeded( diff --git a/src/dawn/pipeline_info.h b/src/dawn/pipeline_info.h index d455d6343..febecca3e 100644 --- a/src/dawn/pipeline_info.h +++ b/src/dawn/pipeline_info.h @@ -39,9 +39,12 @@ struct RenderPipelineInfo { ::dawn::ShaderModule vertex_shader; ::dawn::ShaderModule fragment_shader; + ::dawn::BindGroup bindGroup = {}; + ::dawn::BindGroupLayout bindGroupLayout = nullptr; ::dawn::Color clear_color_value = {0.f, 0.f, 0.f, 0.f}; float clear_depth_value = 1.0f; uint32_t clear_stencil_value = 0; + bool hasBinding = false; /// The framebuffer color render target. This resides on the GPU. ::dawn::Texture fb_texture; diff --git a/tests/cases/draw_rectangles.amber b/tests/cases/draw_rectangles.amber index 9e2e3cb3f..1e801cbb0 100644 --- a/tests/cases/draw_rectangles.amber +++ b/tests/cases/draw_rectangles.amber @@ -48,7 +48,8 @@ BUFFER data_buf2 DATA_TYPE vec4 DATA 0 1 0 1 END BUFFER data_buf3 DATA_TYPE vec4 DATA 0 0 1 1 END BUFFER data_buf4 DATA_TYPE vec4 DATA .5 0 .5 1 END -BUFFER frame FORMAT R32G32B32A32_SFLOAT + +BUFFER frame FORMAT B8G8R8A8_UNORM PIPELINE graphics pipeline1 ATTACH vtex_shader From 6254da96edb9226a792e40963780c94634f646d0 Mon Sep 17 00:00:00 2001 From: SarahM0 Date: Wed, 29 May 2019 10:24:21 -0400 Subject: [PATCH 2/7] add support for BUFFER in amberScript --- src/dawn/engine_dawn.cc | 106 ++++++++++++++++++++++++++++-- tests/cases/draw_rectangles.amber | 3 +- 2 files changed, 101 insertions(+), 8 deletions(-) diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc index 3683d61ed..1cee697e1 100644 --- a/src/dawn/engine_dawn.cc +++ b/src/dawn/engine_dawn.cc @@ -44,7 +44,8 @@ static const float kLodMax = 1000.0; static const uint32_t kMaxColorAttachments = 4u; static const uint32_t kMaxVertexInputs = 16u; static const uint32_t kMaxVertexAttributes = 16u; - +static ::dawn::BindGroupLayout bindGroupLayout; +static bool hasBinding = false; // This structure is a container for a few variables that are created during // CreateRenderPipelineDescriptor and CreateRenderPassDescriptor and we want to // make sure they don't go out of scope before we are done with them @@ -407,6 +408,23 @@ ::dawn::BindGroupBinding BindingInitializationHelper::GetAsBinding() const { return result; } +::dawn::BindGroup MakeBindGroup( + const ::dawn::Device& device, + const ::dawn::BindGroupLayout& layout, + std::vector bindingsInitializer) { + std::vector<::dawn::BindGroupBinding> bindings; + for (const BindingInitializationHelper& helper : bindingsInitializer) { + bindings.push_back(helper.GetAsBinding()); + } + + ::dawn::BindGroupDescriptor descriptor; + descriptor.layout = layout; + descriptor.bindingCount = bindings.size(); + descriptor.bindings = bindings.data(); + + return device.CreateBindGroup(&descriptor); +} + ::dawn::BindGroup MakeBindGroup( const ::dawn::Device& device, const ::dawn::BindGroupLayout& layout, @@ -424,6 +442,26 @@ ::dawn::BindGroup MakeBindGroup( return device.CreateBindGroup(&descriptor); } +// Creates a bind group layout. +// Copied from Dawn utils source code. +::dawn::BindGroupLayout MakeBindGroupLayout( + const ::dawn::Device& device, + std::vector<::dawn::BindGroupLayoutBinding> bindingsInitializer) { + constexpr ::dawn::ShaderStageBit kNoStages{}; + + std::vector<::dawn::BindGroupLayoutBinding> bindings; + for (const ::dawn::BindGroupLayoutBinding& binding : bindingsInitializer) { + if (binding.visibility != kNoStages) { + bindings.push_back(binding); + } + } + + ::dawn::BindGroupLayoutDescriptor descriptor; + descriptor.bindingCount = static_cast(bindings.size()); + descriptor.bindings = bindings.data(); + return device.CreateBindGroupLayout(&descriptor); +} + // Creates a bind group layout. // Copied from Dawn utils source code. ::dawn::BindGroupLayout MakeBindGroupLayout( @@ -565,14 +603,64 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { auto shader = device_->CreateShaderModule(&descriptor); if (!shader) { - return Result("Dawn::SetShader: failed to create shader"); + return Result("Dawn::CreatePipeline: failed to create shader"); } if (module_for_type.count(type)) { - return Result("Dawn::SetShader: module for type already exists"); + return Result("Dawn::CreatePipeline: module for type already exists"); } module_for_type[type] = shader; } + std::vector bih; + std::vector<::dawn::BindGroupLayoutBinding> bi; + ::dawn::ShaderStageBit kAllStages = + ::dawn::ShaderStageBit::Vertex | ::dawn::ShaderStageBit::Fragment; + for (const auto& buf_info : pipeline->GetBuffers()) { +#if 0 + std::cout << buf_info.buffer->ValueCount() << " "; + const auto* data = buf_info.buffer->GetValues(); + for (uint i = 0; i < buf_info.buffer->ValueCount(); i++) { + std::cout << data[i] << " "; + } + std::cout << buf_info.descriptor_set << " "; + std::cout << buf_info.binding << " "; + std::cout << "\n"; +#endif + + ::dawn::Buffer buffer; + if (buf_info.buffer->GetBufferType() == BufferType::kStorage) { + buffer = + CreateBufferFromData(*device_, buf_info.buffer->ValuePtr()->data(), + buf_info.buffer->GetSizeInBytes(), + ::dawn::BufferUsageBit::Storage | + ::dawn::BufferUsageBit::TransferSrc | + ::dawn::BufferUsageBit::TransferDst); + } else if (buf_info.buffer->GetBufferType() == BufferType::kUniform) { + buffer = + CreateBufferFromData(*device_, buf_info.buffer->ValuePtr()->data(), + buf_info.buffer->GetSizeInBytes(), + ::dawn::BufferUsageBit::Uniform | + ::dawn::BufferUsageBit::TransferSrc | + ::dawn::BufferUsageBit::TransferDst); + } else { + return Result("Dawn: CreatePipeline - unknown buffer type: " + + std::to_string(static_cast( + buf_info.buffer->GetBufferType()))); + } + + ::dawn::BindGroupLayoutBinding temp; + temp.binding = buf_info.binding; + temp.visibility = kAllStages; + temp.type = ::dawn::BindingType::StorageBuffer; + bi.push_back(temp); + + BindingInitializationHelper temp_bih(buf_info.binding, buffer, 0, + buf_info.buffer->GetSizeInBytes()); + bih.push_back(temp_bih); + } + if (bi.size() > 0) + bindGroupLayout = MakeBindGroupLayout(*device_, bi); + switch (pipeline->GetType()) { case PipelineType::kCompute: { auto& module = module_for_type[kShaderTypeCompute]; @@ -599,6 +687,11 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { } pipeline_map_[pipeline].render_pipeline.reset( new RenderPipelineInfo(pipeline, vs, fs)); + if (bih.size() > 0) { + pipeline_map_[pipeline].render_pipeline->bindGroup = + MakeBindGroup(*device_, bindGroupLayout, bih); + hasBinding = true; + } break; } } @@ -728,9 +821,9 @@ Result DawnPipelineHelper::CreateRenderPipelineDescriptor( depth_stencil_format = ::dawn::TextureFormat::D32FloatS8Uint; } - if (render_pipeline.hasBinding) + if (hasBinding) renderPipelineDescriptor.layout = - MakeBasicPipelineLayout(device, &render_pipeline.bindGroupLayout); + MakeBasicPipelineLayout(device, &bindGroupLayout); else renderPipelineDescriptor.layout = MakeBasicPipelineLayout(device, nullptr); @@ -983,7 +1076,8 @@ Result EngineDawn::DoPatchParameterVertices( } // ::dawn::CommandBuffer CreateSimpleComputeCommandBuffer( -// const dawn::ComputePipeline& pipeline, const dawn::BindGroup& bindGroup) +// const dawn::ComputePipeline& pipeline, const dawn::BindGroup& +// bindGroup) // { // dawn::CommandEncoder encoder = device.CreateCommandEncoder(); // dawn::ComputePassEncoder pass = encoder.BeginComputePass(); diff --git a/tests/cases/draw_rectangles.amber b/tests/cases/draw_rectangles.amber index 1e801cbb0..9e2e3cb3f 100644 --- a/tests/cases/draw_rectangles.amber +++ b/tests/cases/draw_rectangles.amber @@ -48,8 +48,7 @@ BUFFER data_buf2 DATA_TYPE vec4 DATA 0 1 0 1 END BUFFER data_buf3 DATA_TYPE vec4 DATA 0 0 1 1 END BUFFER data_buf4 DATA_TYPE vec4 DATA .5 0 .5 1 END - -BUFFER frame FORMAT B8G8R8A8_UNORM +BUFFER frame FORMAT R32G32B32A32_SFLOAT PIPELINE graphics pipeline1 ATTACH vtex_shader From 407c197459abd4db93784e7d7f7e243182974b9c Mon Sep 17 00:00:00 2001 From: SarahM0 Date: Fri, 31 May 2019 10:38:22 -0400 Subject: [PATCH 3/7] clean up and set bindings --- src/dawn/engine_dawn.cc | 112 ++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 72 deletions(-) diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc index 1cee697e1..15b97acde 100644 --- a/src/dawn/engine_dawn.cc +++ b/src/dawn/engine_dawn.cc @@ -425,25 +425,7 @@ ::dawn::BindGroup MakeBindGroup( return device.CreateBindGroup(&descriptor); } -::dawn::BindGroup MakeBindGroup( - const ::dawn::Device& device, - const ::dawn::BindGroupLayout& layout, - std::initializer_list bindingsInitializer) { - std::vector<::dawn::BindGroupBinding> bindings; - for (const BindingInitializationHelper& helper : bindingsInitializer) { - bindings.push_back(helper.GetAsBinding()); - } - - ::dawn::BindGroupDescriptor descriptor; - descriptor.layout = layout; - descriptor.bindingCount = bindings.size(); - descriptor.bindings = bindings.data(); - - return device.CreateBindGroup(&descriptor); -} - // Creates a bind group layout. -// Copied from Dawn utils source code. ::dawn::BindGroupLayout MakeBindGroupLayout( const ::dawn::Device& device, std::vector<::dawn::BindGroupLayoutBinding> bindingsInitializer) { @@ -462,26 +444,6 @@ ::dawn::BindGroupLayout MakeBindGroupLayout( return device.CreateBindGroupLayout(&descriptor); } -// Creates a bind group layout. -// Copied from Dawn utils source code. -::dawn::BindGroupLayout MakeBindGroupLayout( - const ::dawn::Device& device, - std::initializer_list<::dawn::BindGroupLayoutBinding> bindingsInitializer) { - constexpr ::dawn::ShaderStageBit kNoStages{}; - - std::vector<::dawn::BindGroupLayoutBinding> bindings; - for (const ::dawn::BindGroupLayoutBinding& binding : bindingsInitializer) { - if (binding.visibility != kNoStages) { - bindings.push_back(binding); - } - } - - ::dawn::BindGroupLayoutDescriptor descriptor; - descriptor.bindingCount = static_cast(bindings.size()); - descriptor.bindings = bindings.data(); - return device.CreateBindGroupLayout(&descriptor); -} - // Creates a basic pipeline layout. // Copied from Dawn utils source code. ::dawn::PipelineLayout MakeBasicPipelineLayout( @@ -611,10 +573,11 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { module_for_type[type] = shader; } - std::vector bih; - std::vector<::dawn::BindGroupLayoutBinding> bi; ::dawn::ShaderStageBit kAllStages = ::dawn::ShaderStageBit::Vertex | ::dawn::ShaderStageBit::Fragment; + std::vector bindingInitalizerHelper; + std::vector<::dawn::BindGroupLayoutBinding> bindGroup; + for (const auto& buf_info : pipeline->GetBuffers()) { #if 0 std::cout << buf_info.buffer->ValueCount() << " "; @@ -626,40 +589,45 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { std::cout << buf_info.binding << " "; std::cout << "\n"; #endif - - ::dawn::Buffer buffer; - if (buf_info.buffer->GetBufferType() == BufferType::kStorage) { - buffer = - CreateBufferFromData(*device_, buf_info.buffer->ValuePtr()->data(), - buf_info.buffer->GetSizeInBytes(), - ::dawn::BufferUsageBit::Storage | - ::dawn::BufferUsageBit::TransferSrc | - ::dawn::BufferUsageBit::TransferDst); - } else if (buf_info.buffer->GetBufferType() == BufferType::kUniform) { - buffer = - CreateBufferFromData(*device_, buf_info.buffer->ValuePtr()->data(), - buf_info.buffer->GetSizeInBytes(), - ::dawn::BufferUsageBit::Uniform | - ::dawn::BufferUsageBit::TransferSrc | - ::dawn::BufferUsageBit::TransferDst); - } else { - return Result("Dawn: CreatePipeline - unknown buffer type: " + - std::to_string(static_cast( - buf_info.buffer->GetBufferType()))); + ::dawn::BufferUsageBit bufferType; + ::dawn::BindingType bindingType; + switch (buf_info.buffer->GetBufferType()) { + case BufferType::kStorage: { + bufferType = ::dawn::BufferUsageBit::Storage; + bindingType = ::dawn::BindingType::StorageBuffer; + break; + } + case BufferType::kUniform: { + bufferType = ::dawn::BufferUsageBit::Uniform; + bindingType = ::dawn::BindingType::UniformBuffer; + break; + } + default: { + return Result("Dawn: CreatePipeline - unknown buffer type: " + + std::to_string(static_cast( + buf_info.buffer->GetBufferType()))); + break; + } } - ::dawn::BindGroupLayoutBinding temp; - temp.binding = buf_info.binding; - temp.visibility = kAllStages; - temp.type = ::dawn::BindingType::StorageBuffer; - bi.push_back(temp); + ::dawn::Buffer buffer = + CreateBufferFromData(*device_, buf_info.buffer->ValuePtr()->data(), + buf_info.buffer->GetSizeInBytes(), + bufferType | ::dawn::BufferUsageBit::TransferSrc | + ::dawn::BufferUsageBit::TransferDst); - BindingInitializationHelper temp_bih(buf_info.binding, buffer, 0, - buf_info.buffer->GetSizeInBytes()); - bih.push_back(temp_bih); + ::dawn::BindGroupLayoutBinding bglb; + bglb.binding = buf_info.binding; + bglb.visibility = kAllStages; + bglb.type = bindingType; + bindGroup.push_back(bglb); + + bindingInitalizerHelper.push_back(BindingInitializationHelper( + buf_info.binding, buffer, 0, buf_info.buffer->GetSizeInBytes())); + } + if (bindGroup.size() > 0) { + bindGroupLayout = MakeBindGroupLayout(*device_, bindGroup); } - if (bi.size() > 0) - bindGroupLayout = MakeBindGroupLayout(*device_, bi); switch (pipeline->GetType()) { case PipelineType::kCompute: { @@ -687,9 +655,9 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { } pipeline_map_[pipeline].render_pipeline.reset( new RenderPipelineInfo(pipeline, vs, fs)); - if (bih.size() > 0) { + if (bindingInitalizerHelper.size() > 0) { pipeline_map_[pipeline].render_pipeline->bindGroup = - MakeBindGroup(*device_, bindGroupLayout, bih); + MakeBindGroup(*device_, bindGroupLayout, bindingInitalizerHelper); hasBinding = true; } break; From 6b87432de02b3c5c09bc68e19358431c54773100 Mon Sep 17 00:00:00 2001 From: SarahM0 Date: Tue, 4 Jun 2019 13:11:25 -0400 Subject: [PATCH 4/7] use relevant binding flag --- src/dawn/engine_dawn.cc | 25 +++++++++++++++---------- src/dawn/pipeline_info.h | 2 -- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc index 15b97acde..580e89853 100644 --- a/src/dawn/engine_dawn.cc +++ b/src/dawn/engine_dawn.cc @@ -589,16 +589,16 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { std::cout << buf_info.binding << " "; std::cout << "\n"; #endif - ::dawn::BufferUsageBit bufferType; + ::dawn::BufferUsageBit bufferUsage; ::dawn::BindingType bindingType; switch (buf_info.buffer->GetBufferType()) { case BufferType::kStorage: { - bufferType = ::dawn::BufferUsageBit::Storage; + bufferUsage = ::dawn::BufferUsageBit::Storage; bindingType = ::dawn::BindingType::StorageBuffer; break; } case BufferType::kUniform: { - bufferType = ::dawn::BufferUsageBit::Uniform; + bufferUsage = ::dawn::BufferUsageBit::Uniform; bindingType = ::dawn::BindingType::UniformBuffer; break; } @@ -613,7 +613,7 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { ::dawn::Buffer buffer = CreateBufferFromData(*device_, buf_info.buffer->ValuePtr()->data(), buf_info.buffer->GetSizeInBytes(), - bufferType | ::dawn::BufferUsageBit::TransferSrc | + bufferUsage | ::dawn::BufferUsageBit::TransferSrc | ::dawn::BufferUsageBit::TransferDst); ::dawn::BindGroupLayoutBinding bglb; @@ -622,8 +622,9 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { bglb.type = bindingType; bindGroup.push_back(bglb); - bindingInitalizerHelper.push_back(BindingInitializationHelper( - buf_info.binding, buffer, 0, buf_info.buffer->GetSizeInBytes())); + BindingInitializationHelper tempBinding = BindingInitializationHelper( + buf_info.binding, buffer, 0, buf_info.buffer->GetSizeInBytes()); + bindingInitalizerHelper.push_back(tempBinding); } if (bindGroup.size() > 0) { bindGroupLayout = MakeBindGroupLayout(*device_, bindGroup); @@ -1008,12 +1009,13 @@ Result EngineDawn::DoDrawRect(const DrawRectCommand* command) { ::dawn::CommandEncoder encoder = device_->CreateCommandEncoder(); ::dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPassDescriptor); + pass.SetPipeline(pipeline); - pass.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets); - pass.SetIndexBuffer(indexBuffer, 0); - if (render_pipeline->hasBinding) { + if (hasBinding) { pass.SetBindGroup(0, render_pipeline->bindGroup, 0, nullptr); } + pass.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets); + pass.SetIndexBuffer(indexBuffer, 0); pass.DrawIndexed(6, 1, 0, 0, 0); pass.EndPass(); @@ -1056,7 +1058,9 @@ Result EngineDawn::DoPatchParameterVertices( // return encoder.Finish(); // } -Result EngineDawn::DoBuffer(const BufferCommand* command) { +Result EngineDawn::DoBuffer(const BufferCommand*) { + return Result("Dawn:DoBuffer not implemented"); +#if 0 // TODO(SarahM0): it can be a compute pipeline too RenderPipelineInfo* render_pipeline = GetRenderPipeline(command); if (!render_pipeline) @@ -1109,6 +1113,7 @@ Result EngineDawn::DoBuffer(const BufferCommand* command) { }, }); return {}; +#endif } Result EngineDawn::CreateFramebufferIfNeeded( diff --git a/src/dawn/pipeline_info.h b/src/dawn/pipeline_info.h index febecca3e..98ccafcdd 100644 --- a/src/dawn/pipeline_info.h +++ b/src/dawn/pipeline_info.h @@ -40,11 +40,9 @@ struct RenderPipelineInfo { ::dawn::ShaderModule vertex_shader; ::dawn::ShaderModule fragment_shader; ::dawn::BindGroup bindGroup = {}; - ::dawn::BindGroupLayout bindGroupLayout = nullptr; ::dawn::Color clear_color_value = {0.f, 0.f, 0.f, 0.f}; float clear_depth_value = 1.0f; uint32_t clear_stencil_value = 0; - bool hasBinding = false; /// The framebuffer color render target. This resides on the GPU. ::dawn::Texture fb_texture; From df351dd2f208e7951ba9bb75ede9a79574febfc9 Mon Sep 17 00:00:00 2001 From: SarahM0 Date: Wed, 5 Jun 2019 12:45:09 -0400 Subject: [PATCH 5/7] added a map for texture and textureView --- src/dawn/engine_dawn.cc | 89 +++++++++++++++++++++++++--------------- src/dawn/engine_dawn.h | 6 +++ src/dawn/pipeline_info.h | 1 + 3 files changed, 64 insertions(+), 32 deletions(-) diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc index 580e89853..da7de69d9 100644 --- a/src/dawn/engine_dawn.cc +++ b/src/dawn/engine_dawn.cc @@ -714,7 +714,7 @@ Result EngineDawn::DoClear(const ClearCommand* command) { // via the load op. The load op is "clear" to the clear colour. ::dawn::RenderPassColorAttachmentDescriptor color_attachment = ::dawn::RenderPassColorAttachmentDescriptor(); - color_attachment.attachment = render_pipeline->fb_texture.CreateDefaultView(); + color_attachment.attachment = render_pipeline->textureView; color_attachment.resolveTarget = nullptr; color_attachment.clearColor = render_pipeline->clear_color_value; color_attachment.loadOp = ::dawn::LoadOp::Clear; @@ -886,7 +886,7 @@ Result DawnPipelineHelper::CreateRenderPassDescriptor( const RenderPipelineInfo& render_pipeline, const ::dawn::Device& device) { std::initializer_list<::dawn::TextureView> colorAttachmentInfo = { - render_pipeline.fb_texture.CreateDefaultView()}; + render_pipeline.textureView}; for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { colorAttachmentsInfo[i].loadOp = ::dawn::LoadOp::Clear; @@ -971,25 +971,27 @@ Result EngineDawn::DoDrawRect(const DrawRectCommand* command) { ::dawn::Buffer indexBuffer = CreateBufferFromData( *device_, indexData, sizeof(indexData), ::dawn::BufferUsageBit::Index); - std::vector values(8); - // Bottom left - values[0].SetDoubleValue(static_cast(x)); - values[1].SetDoubleValue(static_cast(y + rectangleHeight)); - // Top left - values[2].SetDoubleValue(static_cast(x)); - values[3].SetDoubleValue(static_cast(y)); - // Top right - values[4].SetDoubleValue(static_cast(x + rectangleWidth)); - values[5].SetDoubleValue(static_cast(y)); - // Bottom right - values[6].SetDoubleValue(static_cast(x + rectangleWidth)); - values[7].SetDoubleValue(static_cast(y + rectangleHeight)); - - static const float vertexData[4 * 4] = { - values[0].AsFloat(), values[1].AsFloat(), 0.0f, 1.0f, - values[2].AsFloat(), values[3].AsFloat(), 0.0f, 1.0f, - values[4].AsFloat(), values[5].AsFloat(), 0.0f, 1.0f, - values[6].AsFloat(), values[7].AsFloat(), 0.0f, 1.0f, + const float vertexData[4 * 4] = { + // Bottom left + x, + y + rectangleHeight, + 0.0f, + 1.0f, + // Top left + x, + y, + 0.0f, + 1.0f, + // Top right + x + rectangleWidth, + y, + 0.0f, + 1.0f, + // Bottom right + x + rectangleWidth, + y + rectangleHeight, + 0.0f, + 1.0f, }; ::dawn::Buffer vertexBuffer = CreateBufferFromData( @@ -1125,26 +1127,49 @@ Result EngineDawn::CreateFramebufferIfNeeded( const uint32_t width = render_pipeline->pipeline->GetFramebufferWidth(); const uint32_t height = render_pipeline->pipeline->GetFramebufferHeight(); - // TODO(dneto): For now, assume color attachment 0 is the framebuffer. + for (auto colorAttachment : + render_pipeline->pipeline->GetColorAttachments()) { + auto* amber_format = colorAttachment.buffer->GetFormat(); + if (!amber_format) + return Result("Color attachment 0 has no format!"); + ::dawn::TextureFormat fb_format{}; + result = GetDawnTextureFormat(*amber_format, &fb_format); + if (!result.IsSuccess()) + return result; + + uint32_t location; + render_pipeline->pipeline->GetLocationForColorAttachment( + colorAttachment.buffer, &location); + if (colorAttachmentLocationToTextureView_map_.find(location) == + colorAttachmentLocationToTextureView_map_.end()) { + ::dawn::Texture fb_texture; + result = MakeTexture(*device_, fb_format, width, height, &fb_texture); + if (!result.IsSuccess()) + return result; + render_pipeline->fb_texture = std::move(fb_texture); + colorAttachmentLocationToTexture_map_[location] = + &render_pipeline->fb_texture; + render_pipeline->textureView = + render_pipeline->fb_texture.CreateDefaultView(); + colorAttachmentLocationToTextureView_map_[location] = + &render_pipeline->textureView; + } else { + render_pipeline->textureView = + *colorAttachmentLocationToTextureView_map_[location]; + render_pipeline->fb_texture = + *colorAttachmentLocationToTexture_map_[location]; + } + } + auto* amber_format = render_pipeline->pipeline->GetColorAttachments()[0].buffer->GetFormat(); if (!amber_format) return Result("Color attachment 0 has no format!"); - ::dawn::TextureFormat fb_format{}; result = GetDawnTextureFormat(*amber_format, &fb_format); if (!result.IsSuccess()) return result; - { - ::dawn::Texture fb_texture; - - result = MakeTexture(*device_, fb_format, width, height, &fb_texture); - if (!result.IsSuccess()) - return result; - render_pipeline->fb_texture = std::move(fb_texture); - } - // After that, only create the Dawn depth-stencil texture if the Amber // depth-stencil texture exists. auto* depthBuffer = render_pipeline->pipeline->GetDepthBuffer().buffer; diff --git a/src/dawn/engine_dawn.h b/src/dawn/engine_dawn.h index 44a0c2926..d09b6fb56 100644 --- a/src/dawn/engine_dawn.h +++ b/src/dawn/engine_dawn.h @@ -83,6 +83,12 @@ class EngineDawn : public Engine { // Mapping from the generic engine's Pipeline object to our own Dawn-specific // pipelines. std::unordered_map pipeline_map_; + + std::unordered_map + colorAttachmentLocationToTextureView_map_; + + std::unordered_map + colorAttachmentLocationToTexture_map_; }; } // namespace dawn diff --git a/src/dawn/pipeline_info.h b/src/dawn/pipeline_info.h index 98ccafcdd..c79908d77 100644 --- a/src/dawn/pipeline_info.h +++ b/src/dawn/pipeline_info.h @@ -46,6 +46,7 @@ struct RenderPipelineInfo { /// The framebuffer color render target. This resides on the GPU. ::dawn::Texture fb_texture; + ::dawn::TextureView textureView; /// The depth and stencil target. This resides on the GPU. ::dawn::Texture depth_stencil_texture; /// The buffer to which we will copy the rendered pixel values, for From a5af96d14f03111f27795211c982e5dfd2ab4a14 Mon Sep 17 00:00:00 2001 From: SarahM0 Date: Tue, 11 Jun 2019 13:41:35 -0400 Subject: [PATCH 6/7] move binding attributes to the pipeline --- src/dawn/engine_dawn.cc | 23 ++++++++++++----------- src/dawn/pipeline_info.h | 8 +++++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc index da7de69d9..7b3910efc 100644 --- a/src/dawn/engine_dawn.cc +++ b/src/dawn/engine_dawn.cc @@ -44,8 +44,7 @@ static const float kLodMax = 1000.0; static const uint32_t kMaxColorAttachments = 4u; static const uint32_t kMaxVertexInputs = 16u; static const uint32_t kMaxVertexAttributes = 16u; -static ::dawn::BindGroupLayout bindGroupLayout; -static bool hasBinding = false; + // This structure is a container for a few variables that are created during // CreateRenderPipelineDescriptor and CreateRenderPassDescriptor and we want to // make sure they don't go out of scope before we are done with them @@ -626,9 +625,6 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { buf_info.binding, buffer, 0, buf_info.buffer->GetSizeInBytes()); bindingInitalizerHelper.push_back(tempBinding); } - if (bindGroup.size() > 0) { - bindGroupLayout = MakeBindGroupLayout(*device_, bindGroup); - } switch (pipeline->GetType()) { case PipelineType::kCompute: { @@ -656,10 +652,15 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { } pipeline_map_[pipeline].render_pipeline.reset( new RenderPipelineInfo(pipeline, vs, fs)); + if (bindGroup.size() > 0) { + pipeline_map_[pipeline].render_pipeline->bindGroupLayout = + MakeBindGroupLayout(*device_, bindGroup); + } if (bindingInitalizerHelper.size() > 0) { - pipeline_map_[pipeline].render_pipeline->bindGroup = - MakeBindGroup(*device_, bindGroupLayout, bindingInitalizerHelper); - hasBinding = true; + pipeline_map_[pipeline].render_pipeline->bindGroup = MakeBindGroup( + *device_, pipeline_map_[pipeline].render_pipeline->bindGroupLayout, + bindingInitalizerHelper); + pipeline_map_[pipeline].render_pipeline->hasBinding = true; } break; } @@ -790,9 +791,9 @@ Result DawnPipelineHelper::CreateRenderPipelineDescriptor( depth_stencil_format = ::dawn::TextureFormat::D32FloatS8Uint; } - if (hasBinding) + if (render_pipeline.hasBinding) renderPipelineDescriptor.layout = - MakeBasicPipelineLayout(device, &bindGroupLayout); + MakeBasicPipelineLayout(device, &render_pipeline.bindGroupLayout); else renderPipelineDescriptor.layout = MakeBasicPipelineLayout(device, nullptr); @@ -1013,7 +1014,7 @@ Result EngineDawn::DoDrawRect(const DrawRectCommand* command) { encoder.BeginRenderPass(renderPassDescriptor); pass.SetPipeline(pipeline); - if (hasBinding) { + if (render_pipeline->hasBinding) { pass.SetBindGroup(0, render_pipeline->bindGroup, 0, nullptr); } pass.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets); diff --git a/src/dawn/pipeline_info.h b/src/dawn/pipeline_info.h index c79908d77..c25ec07d6 100644 --- a/src/dawn/pipeline_info.h +++ b/src/dawn/pipeline_info.h @@ -30,8 +30,7 @@ namespace dawn { /// Stores information relating to a graphics pipeline in Dawn. struct RenderPipelineInfo { RenderPipelineInfo() {} - RenderPipelineInfo(::amber::Pipeline* the_pipeline, - ::dawn::ShaderModule vert, + RenderPipelineInfo(::amber::Pipeline* the_pipeline, ::dawn::ShaderModule vert, ::dawn::ShaderModule frag) : pipeline(the_pipeline), vertex_shader(vert), fragment_shader(frag) {} @@ -39,7 +38,6 @@ struct RenderPipelineInfo { ::dawn::ShaderModule vertex_shader; ::dawn::ShaderModule fragment_shader; - ::dawn::BindGroup bindGroup = {}; ::dawn::Color clear_color_value = {0.f, 0.f, 0.f, 0.f}; float clear_depth_value = 1.0f; uint32_t clear_stencil_value = 0; @@ -63,6 +61,10 @@ struct RenderPipelineInfo { /// The number of data bytes in the framebuffer host-side buffer. uint32_t fb_size = 0; + bool hasBinding = false; + ::dawn::BindGroup bindGroup; + ::dawn::BindGroupLayout bindGroupLayout; + // TODO(dneto): Record index data // TODO(dneto): Record buffer data }; From 91c6e07d55d13057f3e5b2faf30b2bff18c5bf89 Mon Sep 17 00:00:00 2001 From: SarahM0 Date: Tue, 11 Jun 2019 14:01:01 -0400 Subject: [PATCH 7/7] move add buffer to ifNeeded --- src/dawn/engine_dawn.cc | 137 ++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 74 deletions(-) diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc index 7b3910efc..334d005f8 100644 --- a/src/dawn/engine_dawn.cc +++ b/src/dawn/engine_dawn.cc @@ -572,60 +572,6 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { module_for_type[type] = shader; } - ::dawn::ShaderStageBit kAllStages = - ::dawn::ShaderStageBit::Vertex | ::dawn::ShaderStageBit::Fragment; - std::vector bindingInitalizerHelper; - std::vector<::dawn::BindGroupLayoutBinding> bindGroup; - - for (const auto& buf_info : pipeline->GetBuffers()) { -#if 0 - std::cout << buf_info.buffer->ValueCount() << " "; - const auto* data = buf_info.buffer->GetValues(); - for (uint i = 0; i < buf_info.buffer->ValueCount(); i++) { - std::cout << data[i] << " "; - } - std::cout << buf_info.descriptor_set << " "; - std::cout << buf_info.binding << " "; - std::cout << "\n"; -#endif - ::dawn::BufferUsageBit bufferUsage; - ::dawn::BindingType bindingType; - switch (buf_info.buffer->GetBufferType()) { - case BufferType::kStorage: { - bufferUsage = ::dawn::BufferUsageBit::Storage; - bindingType = ::dawn::BindingType::StorageBuffer; - break; - } - case BufferType::kUniform: { - bufferUsage = ::dawn::BufferUsageBit::Uniform; - bindingType = ::dawn::BindingType::UniformBuffer; - break; - } - default: { - return Result("Dawn: CreatePipeline - unknown buffer type: " + - std::to_string(static_cast( - buf_info.buffer->GetBufferType()))); - break; - } - } - - ::dawn::Buffer buffer = - CreateBufferFromData(*device_, buf_info.buffer->ValuePtr()->data(), - buf_info.buffer->GetSizeInBytes(), - bufferUsage | ::dawn::BufferUsageBit::TransferSrc | - ::dawn::BufferUsageBit::TransferDst); - - ::dawn::BindGroupLayoutBinding bglb; - bglb.binding = buf_info.binding; - bglb.visibility = kAllStages; - bglb.type = bindingType; - bindGroup.push_back(bglb); - - BindingInitializationHelper tempBinding = BindingInitializationHelper( - buf_info.binding, buffer, 0, buf_info.buffer->GetSizeInBytes()); - bindingInitalizerHelper.push_back(tempBinding); - } - switch (pipeline->GetType()) { case PipelineType::kCompute: { auto& module = module_for_type[kShaderTypeCompute]; @@ -652,16 +598,7 @@ Result EngineDawn::CreatePipeline(::amber::Pipeline* pipeline) { } pipeline_map_[pipeline].render_pipeline.reset( new RenderPipelineInfo(pipeline, vs, fs)); - if (bindGroup.size() > 0) { - pipeline_map_[pipeline].render_pipeline->bindGroupLayout = - MakeBindGroupLayout(*device_, bindGroup); - } - if (bindingInitalizerHelper.size() > 0) { - pipeline_map_[pipeline].render_pipeline->bindGroup = MakeBindGroup( - *device_, pipeline_map_[pipeline].render_pipeline->bindGroupLayout, - bindingInitalizerHelper); - pipeline_map_[pipeline].render_pipeline->hasBinding = true; - } + CreateFramebufferIfNeeded(pipeline_map_[pipeline].render_pipeline.get()); break; } } @@ -703,12 +640,6 @@ Result EngineDawn::DoClear(const ClearCommand* command) { if (!render_pipeline) return Result("Clear invoked on invalid or missing render pipeline"); - // TODO(dneto): Likely, we can create the render objects during - // CreatePipeline. - Result result = CreateFramebufferIfNeeded(render_pipeline); - if (!result.IsSuccess()) - return result; - // Record a render pass in a command on the command buffer. // // First describe the color attachments, and how they are initialized @@ -890,7 +821,7 @@ Result DawnPipelineHelper::CreateRenderPassDescriptor( render_pipeline.textureView}; for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { - colorAttachmentsInfo[i].loadOp = ::dawn::LoadOp::Clear; + colorAttachmentsInfo[i].loadOp = ::dawn::LoadOp::Load; colorAttachmentsInfo[i].storeOp = ::dawn::StoreOp::Store; colorAttachmentsInfo[i].clearColor = render_pipeline.clear_color_value; colorAttachmentsInfoPtr[i] = nullptr; @@ -946,9 +877,6 @@ Result EngineDawn::DoDrawRect(const DrawRectCommand* command) { RenderPipelineInfo* render_pipeline = GetRenderPipeline(command); if (!render_pipeline) return Result("DrawRect invoked on invalid or missing render pipeline"); - Result result = CreateFramebufferIfNeeded(render_pipeline); - if (!result.IsSuccess()) - return result; float x = command->GetX(); float y = command->GetY(); @@ -1215,6 +1143,67 @@ Result EngineDawn::CreateFramebufferIfNeeded( render_pipeline->fb_size = size; } + ::dawn::ShaderStageBit kAllStages = + ::dawn::ShaderStageBit::Vertex | ::dawn::ShaderStageBit::Fragment; + std::vector bindingInitalizerHelper; + std::vector<::dawn::BindGroupLayoutBinding> bindGroup; + + for (const auto& buf_info : render_pipeline->pipeline->GetBuffers()) { +#if 0 + std::cout << buf_info.buffer->ValueCount() << " "; + const auto* data = buf_info.buffer->GetValues(); + for (uint i = 0; i < buf_info.buffer->ValueCount(); i++) { + std::cout << data[i] << " "; + } + std::cout << buf_info.descriptor_set << " "; + std::cout << buf_info.binding << " "; + std::cout << "\n"; +#endif + ::dawn::BufferUsageBit bufferUsage; + ::dawn::BindingType bindingType; + switch (buf_info.buffer->GetBufferType()) { + case BufferType::kStorage: { + bufferUsage = ::dawn::BufferUsageBit::Storage; + bindingType = ::dawn::BindingType::StorageBuffer; + break; + } + case BufferType::kUniform: { + bufferUsage = ::dawn::BufferUsageBit::Uniform; + bindingType = ::dawn::BindingType::UniformBuffer; + break; + } + default: { + return Result("Dawn: CreatePipeline - unknown buffer type: " + + std::to_string(static_cast( + buf_info.buffer->GetBufferType()))); + break; + } + } + + ::dawn::Buffer buffer = + CreateBufferFromData(*device_, buf_info.buffer->ValuePtr()->data(), + buf_info.buffer->GetSizeInBytes(), + bufferUsage | ::dawn::BufferUsageBit::TransferSrc | + ::dawn::BufferUsageBit::TransferDst); + + ::dawn::BindGroupLayoutBinding bglb; + bglb.binding = buf_info.binding; + bglb.visibility = kAllStages; + bglb.type = bindingType; + bindGroup.push_back(bglb); + + BindingInitializationHelper tempBinding = BindingInitializationHelper( + buf_info.binding, buffer, 0, buf_info.buffer->GetSizeInBytes()); + bindingInitalizerHelper.push_back(tempBinding); + } + + if (bindGroup.size() > 0 && bindingInitalizerHelper.size() > 0) { + render_pipeline->bindGroupLayout = MakeBindGroupLayout(*device_, bindGroup); + render_pipeline->bindGroup = MakeBindGroup( + *device_, render_pipeline->bindGroupLayout, bindingInitalizerHelper); + render_pipeline->hasBinding = true; + } + return {}; }