// Copyright 2017 The NXT Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "backend/Pipeline.h" #include "backend/DepthStencilState.h" #include "backend/Device.h" #include "backend/InputState.h" #include "backend/PipelineLayout.h" #include "backend/ShaderModule.h" namespace backend { // PipelineBase PipelineBase::PipelineBase(PipelineBuilder* builder) : mStageMask(builder->mStageMask), mLayout(std::move(builder->mLayout)) { if (!mLayout) { nxt::PipelineLayoutDescriptor descriptor; descriptor.numBindGroupLayouts = 0; descriptor.bindGroupLayouts = nullptr; mLayout = builder->GetParentBuilder()->GetDevice()->CreatePipelineLayout(&descriptor); // Remove the external ref objects are created with mLayout->Release(); } auto FillPushConstants = [](const ShaderModuleBase* module, PushConstantInfo* info) { const auto& moduleInfo = module->GetPushConstants(); info->mask = moduleInfo.mask; for (uint32_t i = 0; i < moduleInfo.names.size(); i++) { uint32_t size = moduleInfo.sizes[i]; if (size == 0) { continue; } for (uint32_t offset = 0; offset < size; offset++) { info->types[i + offset] = moduleInfo.types[i]; } i += size - 1; } }; for (auto stageBit : IterateStages(builder->mStageMask)) { if (!builder->mStages[stageBit].module->IsCompatibleWithPipelineLayout(mLayout.Get())) { builder->GetParentBuilder()->HandleError("Stage not compatible with layout"); return; } FillPushConstants(builder->mStages[stageBit].module.Get(), &mPushConstants[stageBit]); } } const PipelineBase::PushConstantInfo& PipelineBase::GetPushConstants( nxt::ShaderStage stage) const { return mPushConstants[stage]; } nxt::ShaderStageBit PipelineBase::GetStageMask() const { return mStageMask; } PipelineLayoutBase* PipelineBase::GetLayout() { return mLayout.Get(); } // PipelineBuilder PipelineBuilder::PipelineBuilder(BuilderBase* parentBuilder) : mParentBuilder(parentBuilder), mStageMask(static_cast(0)) { } const PipelineBuilder::StageInfo& PipelineBuilder::GetStageInfo(nxt::ShaderStage stage) const { ASSERT(mStageMask & StageBit(stage)); return mStages[stage]; } BuilderBase* PipelineBuilder::GetParentBuilder() const { return mParentBuilder; } void PipelineBuilder::SetLayout(PipelineLayoutBase* layout) { mLayout = layout; } void PipelineBuilder::SetStage(nxt::ShaderStage stage, ShaderModuleBase* module, const char* entryPoint) { if (entryPoint != std::string("main")) { mParentBuilder->HandleError("Currently the entry point has to be main()"); return; } if (stage != module->GetExecutionModel()) { mParentBuilder->HandleError("Setting module with wrong execution model"); return; } nxt::ShaderStageBit bit = StageBit(stage); if (mStageMask & bit) { mParentBuilder->HandleError("Setting already set stage"); return; } mStageMask |= bit; mStages[stage].module = module; mStages[stage].entryPoint = entryPoint; } } // namespace backend