OpenGL: Make GLSL generation per-entrypoint.

Bug: dawn:216
Change-Id: I7b4c0e9c210af59711318a744d8055cfb9b82092
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/28242
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Corentin Wallez 2020-09-09 22:51:37 +00:00 committed by Commit Bot service account
parent 676e8f39df
commit 28efed139f
8 changed files with 49 additions and 47 deletions

View File

@ -104,6 +104,10 @@ namespace dawn_native {
return mStages[stage]; return mStages[stage];
} }
const PerStage<ProgrammableStage>& PipelineBase::GetAllStages() const {
return mStages;
}
MaybeError PipelineBase::ValidateGetBindGroupLayout(uint32_t groupIndex) { MaybeError PipelineBase::ValidateGetBindGroupLayout(uint32_t groupIndex) {
DAWN_TRY(GetDevice()->ValidateIsAlive()); DAWN_TRY(GetDevice()->ValidateIsAlive());
DAWN_TRY(GetDevice()->ValidateObject(this)); DAWN_TRY(GetDevice()->ValidateObject(this));

View File

@ -47,6 +47,7 @@ namespace dawn_native {
const PipelineLayoutBase* GetLayout() const; const PipelineLayoutBase* GetLayout() const;
const RequiredBufferSizes& GetMinBufferSizes() const; const RequiredBufferSizes& GetMinBufferSizes() const;
const ProgrammableStage& GetStage(SingleShaderStage stage) const; const ProgrammableStage& GetStage(SingleShaderStage stage) const;
const PerStage<ProgrammableStage>& GetAllStages() const;
BindGroupLayoutBase* GetBindGroupLayout(uint32_t groupIndex); BindGroupLayoutBase* GetBindGroupLayout(uint32_t groupIndex);

View File

@ -23,7 +23,7 @@ namespace dawn_native { namespace opengl {
PerStage<const ShaderModule*> modules(nullptr); PerStage<const ShaderModule*> modules(nullptr);
modules[SingleShaderStage::Compute] = ToBackend(descriptor->computeStage.module); modules[SingleShaderStage::Compute] = ToBackend(descriptor->computeStage.module);
PipelineGL::Initialize(device->gl, ToBackend(descriptor->layout), modules); PipelineGL::Initialize(device->gl, ToBackend(descriptor->layout), GetAllStages());
} }
void ComputePipeline::ApplyNow() { void ComputePipeline::ApplyNow() {

View File

@ -17,6 +17,7 @@
#include "common/BitSetIterator.h" #include "common/BitSetIterator.h"
#include "common/Log.h" #include "common/Log.h"
#include "dawn_native/BindGroupLayout.h" #include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Pipeline.h"
#include "dawn_native/opengl/Forward.h" #include "dawn_native/opengl/Forward.h"
#include "dawn_native/opengl/OpenGLFunctions.h" #include "dawn_native/opengl/OpenGLFunctions.h"
#include "dawn_native/opengl/PipelineLayoutGL.h" #include "dawn_native/opengl/PipelineLayoutGL.h"
@ -48,7 +49,7 @@ namespace dawn_native { namespace opengl {
void PipelineGL::Initialize(const OpenGLFunctions& gl, void PipelineGL::Initialize(const OpenGLFunctions& gl,
const PipelineLayout* layout, const PipelineLayout* layout,
const PerStage<const ShaderModule*>& modules) { const PerStage<ProgrammableStage>& stages) {
auto CreateShader = [](const OpenGLFunctions& gl, GLenum type, auto CreateShader = [](const OpenGLFunctions& gl, GLenum type,
const char* source) -> GLuint { const char* source) -> GLuint {
GLuint shader = gl.CreateShader(type); GLuint shader = gl.CreateShader(type);
@ -73,18 +74,25 @@ namespace dawn_native { namespace opengl {
mProgram = gl.CreateProgram(); mProgram = gl.CreateProgram();
// Compute the set of active stages.
wgpu::ShaderStage activeStages = wgpu::ShaderStage::None; wgpu::ShaderStage activeStages = wgpu::ShaderStage::None;
for (SingleShaderStage stage : IterateStages(kAllStages)) { for (SingleShaderStage stage : IterateStages(kAllStages)) {
if (modules[stage] != nullptr) { if (stages[stage].module != nullptr) {
activeStages |= StageBit(stage); activeStages |= StageBit(stage);
} }
} }
// Create an OpenGL shader for each stage and gather the list of combined samplers.
PerStage<CombinedSamplerInfo> combinedSamplers;
for (SingleShaderStage stage : IterateStages(activeStages)) { for (SingleShaderStage stage : IterateStages(activeStages)) {
GLuint shader = CreateShader(gl, GLShaderType(stage), modules[stage]->GetSource()); const ShaderModule* module = ToBackend(stages[stage].module.Get());
std::string glsl = module->TranslateToGLSL(stages[stage].entryPoint.c_str(), stage,
&combinedSamplers[stage]);
GLuint shader = CreateShader(gl, GLShaderType(stage), glsl.c_str());
gl.AttachShader(mProgram, shader); gl.AttachShader(mProgram, shader);
} }
// Link all the shaders together.
gl.LinkProgram(mProgram); gl.LinkProgram(mProgram);
GLint linkStatus = GL_FALSE; GLint linkStatus = GL_FALSE;
@ -100,10 +108,9 @@ namespace dawn_native { namespace opengl {
} }
} }
gl.UseProgram(mProgram);
// The uniforms are part of the program state so we can pre-bind buffer units, texture units // The uniforms are part of the program state so we can pre-bind buffer units, texture units
// etc. // etc.
gl.UseProgram(mProgram);
const auto& indices = layout->GetBindingIndexInfo(); const auto& indices = layout->GetBindingIndexInfo();
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) { for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
@ -154,8 +161,6 @@ namespace dawn_native { namespace opengl {
case wgpu::BindingType::StorageTexture: case wgpu::BindingType::StorageTexture:
UNREACHABLE(); UNREACHABLE();
break; break;
// TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
} }
} }
} }
@ -164,7 +169,7 @@ namespace dawn_native { namespace opengl {
{ {
std::set<CombinedSampler> combinedSamplersSet; std::set<CombinedSampler> combinedSamplersSet;
for (SingleShaderStage stage : IterateStages(activeStages)) { for (SingleShaderStage stage : IterateStages(activeStages)) {
for (const auto& combined : modules[stage]->GetCombinedSamplerInfo()) { for (const CombinedSampler& combined : combinedSamplers[stage]) {
combinedSamplersSet.insert(combined); combinedSamplersSet.insert(combined);
} }
} }

View File

@ -17,16 +17,20 @@
#include "dawn_native/Pipeline.h" #include "dawn_native/Pipeline.h"
#include "dawn_native/PerStage.h"
#include "dawn_native/opengl/opengl_platform.h" #include "dawn_native/opengl/opengl_platform.h"
#include <vector> #include <vector>
namespace dawn_native {
struct ProgrammableStage;
} // namespace dawn_native
namespace dawn_native { namespace opengl { namespace dawn_native { namespace opengl {
struct OpenGLFunctions; struct OpenGLFunctions;
class PersistentPipelineState; class PersistentPipelineState;
class PipelineLayout; class PipelineLayout;
class ShaderModule;
class PipelineGL { class PipelineGL {
public: public:
@ -34,7 +38,7 @@ namespace dawn_native { namespace opengl {
void Initialize(const OpenGLFunctions& gl, void Initialize(const OpenGLFunctions& gl,
const PipelineLayout* layout, const PipelineLayout* layout,
const PerStage<const ShaderModule*>& modules); const PerStage<ProgrammableStage>& stages);
// For each unit a sampler is bound to we need to know if we should use filtering or not // For each unit a sampler is bound to we need to know if we should use filtering or not
// because int and uint texture are only complete without filtering. // because int and uint texture are only complete without filtering.

View File

@ -204,7 +204,7 @@ namespace dawn_native { namespace opengl {
modules[SingleShaderStage::Vertex] = ToBackend(descriptor->vertexStage.module); modules[SingleShaderStage::Vertex] = ToBackend(descriptor->vertexStage.module);
modules[SingleShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module); modules[SingleShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module);
PipelineGL::Initialize(device->gl, ToBackend(GetLayout()), modules); PipelineGL::Initialize(device->gl, ToBackend(GetLayout()), GetAllStages());
CreateVAOForVertexState(descriptor->vertexState); CreateVAOForVertexState(descriptor->vertexState);
} }

View File

@ -16,6 +16,7 @@
#include "common/Assert.h" #include "common/Assert.h"
#include "common/Platform.h" #include "common/Platform.h"
#include "dawn_native/SpirvUtils.h"
#include "dawn_native/opengl/DeviceGL.h" #include "dawn_native/opengl/DeviceGL.h"
#include <spirv_glsl.hpp> #include <spirv_glsl.hpp>
@ -54,26 +55,17 @@ namespace dawn_native { namespace opengl {
ResultOrError<ShaderModule*> ShaderModule::Create(Device* device, ResultOrError<ShaderModule*> ShaderModule::Create(Device* device,
const ShaderModuleDescriptor* descriptor) { const ShaderModuleDescriptor* descriptor) {
Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor)); Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor));
DAWN_TRY(module->Initialize()); DAWN_TRY(module->InitializeBase());
return module.Detach(); return module.Detach();
} }
const char* ShaderModule::GetSource() const {
return mGlslSource.c_str();
}
const ShaderModule::CombinedSamplerInfo& ShaderModule::GetCombinedSamplerInfo() const {
return mCombinedInfo;
}
ShaderModule::ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor) ShaderModule::ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor)
: ShaderModuleBase(device, descriptor) { : ShaderModuleBase(device, descriptor) {
} }
MaybeError ShaderModule::Initialize() { std::string ShaderModule::TranslateToGLSL(const char* entryPointName,
DAWN_TRY(InitializeBase()); SingleShaderStage stage,
const std::vector<uint32_t>& spirv = GetSpirv(); CombinedSamplerInfo* combinedSamplers) const {
// If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to // If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to
// be updated. // be updated.
spirv_cross::CompilerGLSL::Options options; spirv_cross::CompilerGLSL::Options options;
@ -92,31 +84,32 @@ namespace dawn_native { namespace opengl {
options.version = 440; options.version = 440;
#endif #endif
spirv_cross::CompilerGLSL compiler(spirv); spirv_cross::CompilerGLSL compiler(GetSpirv());
compiler.set_common_options(options); compiler.set_common_options(options);
compiler.set_entry_point(entryPointName, ShaderStageToExecutionModel(stage));
// Extract bindings names so that it can be used to get its location in program. // Extract bindings names so that it can be used to get its location in program.
// Now translate the separate sampler / textures into combined ones and store their info. // Now translate the separate sampler / textures into combined ones and store their info. We
// We need to do this before removing the set and binding decorations. // need to do this before removing the set and binding decorations.
compiler.build_combined_image_samplers(); compiler.build_combined_image_samplers();
for (const auto& combined : compiler.get_combined_image_samplers()) { for (const auto& combined : compiler.get_combined_image_samplers()) {
mCombinedInfo.emplace_back(); combinedSamplers->emplace_back();
auto& info = mCombinedInfo.back(); CombinedSampler* info = &combinedSamplers->back();
info.samplerLocation.group = BindGroupIndex( info->samplerLocation.group = BindGroupIndex(
compiler.get_decoration(combined.sampler_id, spv::DecorationDescriptorSet)); compiler.get_decoration(combined.sampler_id, spv::DecorationDescriptorSet));
info.samplerLocation.binding = info->samplerLocation.binding =
BindingNumber(compiler.get_decoration(combined.sampler_id, spv::DecorationBinding)); BindingNumber(compiler.get_decoration(combined.sampler_id, spv::DecorationBinding));
info.textureLocation.group = BindGroupIndex( info->textureLocation.group = BindGroupIndex(
compiler.get_decoration(combined.image_id, spv::DecorationDescriptorSet)); compiler.get_decoration(combined.image_id, spv::DecorationDescriptorSet));
info.textureLocation.binding = info->textureLocation.binding =
BindingNumber(compiler.get_decoration(combined.image_id, spv::DecorationBinding)); BindingNumber(compiler.get_decoration(combined.image_id, spv::DecorationBinding));
compiler.set_name(combined.combined_id, info.GetName()); compiler.set_name(combined.combined_id, info->GetName());
} }
const EntryPointMetadata::BindingInfo& bindingInfo = const EntryPointMetadata::BindingInfo& bindingInfo =
GetEntryPoint("main", GetMainEntryPointStageForTransition()).bindings; GetEntryPoint(entryPointName, stage).bindings;
// Change binding names to be "dawn_binding_<group>_<binding>". // Change binding names to be "dawn_binding_<group>_<binding>".
// Also unsets the SPIRV "Binding" decoration as it outputs "layout(binding=)" which // Also unsets the SPIRV "Binding" decoration as it outputs "layout(binding=)" which
@ -146,9 +139,7 @@ namespace dawn_native { namespace opengl {
} }
} }
mGlslSource = compiler.compile(); return compiler.compile();
return {};
} }
}} // namespace dawn_native::opengl }} // namespace dawn_native::opengl

View File

@ -38,23 +38,20 @@ namespace dawn_native { namespace opengl {
}; };
bool operator<(const CombinedSampler& a, const CombinedSampler& b); bool operator<(const CombinedSampler& a, const CombinedSampler& b);
using CombinedSamplerInfo = std::vector<CombinedSampler>;
class ShaderModule final : public ShaderModuleBase { class ShaderModule final : public ShaderModuleBase {
public: public:
static ResultOrError<ShaderModule*> Create(Device* device, static ResultOrError<ShaderModule*> Create(Device* device,
const ShaderModuleDescriptor* descriptor); const ShaderModuleDescriptor* descriptor);
using CombinedSamplerInfo = std::vector<CombinedSampler>; std::string TranslateToGLSL(const char* entryPointName,
SingleShaderStage stage,
const char* GetSource() const; CombinedSamplerInfo* combinedSamplers) const;
const CombinedSamplerInfo& GetCombinedSamplerInfo() const;
private: private:
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor); ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
~ShaderModule() override = default; ~ShaderModule() override = default;
MaybeError Initialize();
CombinedSamplerInfo mCombinedInfo;
std::string mGlslSource;
}; };
}} // namespace dawn_native::opengl }} // namespace dawn_native::opengl