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];
}
const PerStage<ProgrammableStage>& PipelineBase::GetAllStages() const {
return mStages;
}
MaybeError PipelineBase::ValidateGetBindGroupLayout(uint32_t groupIndex) {
DAWN_TRY(GetDevice()->ValidateIsAlive());
DAWN_TRY(GetDevice()->ValidateObject(this));

View File

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

View File

@ -23,7 +23,7 @@ namespace dawn_native { namespace opengl {
PerStage<const ShaderModule*> modules(nullptr);
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() {

View File

@ -17,6 +17,7 @@
#include "common/BitSetIterator.h"
#include "common/Log.h"
#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Pipeline.h"
#include "dawn_native/opengl/Forward.h"
#include "dawn_native/opengl/OpenGLFunctions.h"
#include "dawn_native/opengl/PipelineLayoutGL.h"
@ -48,7 +49,7 @@ namespace dawn_native { namespace opengl {
void PipelineGL::Initialize(const OpenGLFunctions& gl,
const PipelineLayout* layout,
const PerStage<const ShaderModule*>& modules) {
const PerStage<ProgrammableStage>& stages) {
auto CreateShader = [](const OpenGLFunctions& gl, GLenum type,
const char* source) -> GLuint {
GLuint shader = gl.CreateShader(type);
@ -73,18 +74,25 @@ namespace dawn_native { namespace opengl {
mProgram = gl.CreateProgram();
// Compute the set of active stages.
wgpu::ShaderStage activeStages = wgpu::ShaderStage::None;
for (SingleShaderStage stage : IterateStages(kAllStages)) {
if (modules[stage] != nullptr) {
if (stages[stage].module != nullptr) {
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)) {
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);
}
// Link all the shaders together.
gl.LinkProgram(mProgram);
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
// etc.
gl.UseProgram(mProgram);
const auto& indices = layout->GetBindingIndexInfo();
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
@ -154,8 +161,6 @@ namespace dawn_native { namespace opengl {
case wgpu::BindingType::StorageTexture:
UNREACHABLE();
break;
// TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
}
}
}
@ -164,7 +169,7 @@ namespace dawn_native { namespace opengl {
{
std::set<CombinedSampler> combinedSamplersSet;
for (SingleShaderStage stage : IterateStages(activeStages)) {
for (const auto& combined : modules[stage]->GetCombinedSamplerInfo()) {
for (const CombinedSampler& combined : combinedSamplers[stage]) {
combinedSamplersSet.insert(combined);
}
}

View File

@ -17,16 +17,20 @@
#include "dawn_native/Pipeline.h"
#include "dawn_native/PerStage.h"
#include "dawn_native/opengl/opengl_platform.h"
#include <vector>
namespace dawn_native {
struct ProgrammableStage;
} // namespace dawn_native
namespace dawn_native { namespace opengl {
struct OpenGLFunctions;
class PersistentPipelineState;
class PipelineLayout;
class ShaderModule;
class PipelineGL {
public:
@ -34,7 +38,7 @@ namespace dawn_native { namespace opengl {
void Initialize(const OpenGLFunctions& gl,
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
// 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::Fragment] = ToBackend(descriptor->fragmentStage->module);
PipelineGL::Initialize(device->gl, ToBackend(GetLayout()), modules);
PipelineGL::Initialize(device->gl, ToBackend(GetLayout()), GetAllStages());
CreateVAOForVertexState(descriptor->vertexState);
}

View File

@ -16,6 +16,7 @@
#include "common/Assert.h"
#include "common/Platform.h"
#include "dawn_native/SpirvUtils.h"
#include "dawn_native/opengl/DeviceGL.h"
#include <spirv_glsl.hpp>
@ -54,26 +55,17 @@ namespace dawn_native { namespace opengl {
ResultOrError<ShaderModule*> ShaderModule::Create(Device* device,
const ShaderModuleDescriptor* descriptor) {
Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor));
DAWN_TRY(module->Initialize());
DAWN_TRY(module->InitializeBase());
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)
: ShaderModuleBase(device, descriptor) {
}
MaybeError ShaderModule::Initialize() {
DAWN_TRY(InitializeBase());
const std::vector<uint32_t>& spirv = GetSpirv();
std::string ShaderModule::TranslateToGLSL(const char* entryPointName,
SingleShaderStage stage,
CombinedSamplerInfo* combinedSamplers) const {
// If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to
// be updated.
spirv_cross::CompilerGLSL::Options options;
@ -92,31 +84,32 @@ namespace dawn_native { namespace opengl {
options.version = 440;
#endif
spirv_cross::CompilerGLSL compiler(spirv);
spirv_cross::CompilerGLSL compiler(GetSpirv());
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.
// Now translate the separate sampler / textures into combined ones and store their info.
// We need to do this before removing the set and binding decorations.
// Now translate the separate sampler / textures into combined ones and store their info. We
// need to do this before removing the set and binding decorations.
compiler.build_combined_image_samplers();
for (const auto& combined : compiler.get_combined_image_samplers()) {
mCombinedInfo.emplace_back();
combinedSamplers->emplace_back();
auto& info = mCombinedInfo.back();
info.samplerLocation.group = BindGroupIndex(
CombinedSampler* info = &combinedSamplers->back();
info->samplerLocation.group = BindGroupIndex(
compiler.get_decoration(combined.sampler_id, spv::DecorationDescriptorSet));
info.samplerLocation.binding =
info->samplerLocation.binding =
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));
info.textureLocation.binding =
info->textureLocation.binding =
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 =
GetEntryPoint("main", GetMainEntryPointStageForTransition()).bindings;
GetEntryPoint(entryPointName, stage).bindings;
// Change binding names to be "dawn_binding_<group>_<binding>".
// 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 {};
return compiler.compile();
}
}} // namespace dawn_native::opengl

View File

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