Cache WGSL -> GLSL compilation
Fixed: dawn:1480 Change-Id: I5c1453a4e37d0e97805391a6c807091d0a8fc1c7 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/98281 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
e62fbbc75c
commit
8830991b41
|
@ -62,6 +62,10 @@ bool OpenGLVersion::IsES() const {
|
|||
return mStandard == Standard::ES;
|
||||
}
|
||||
|
||||
OpenGLVersion::Standard OpenGLVersion::GetStandard() const {
|
||||
return mStandard;
|
||||
}
|
||||
|
||||
uint32_t OpenGLVersion::GetMajor() const {
|
||||
return mMajorVersion;
|
||||
}
|
||||
|
|
|
@ -21,19 +21,21 @@ namespace dawn::native::opengl {
|
|||
|
||||
struct OpenGLVersion {
|
||||
public:
|
||||
enum class Standard {
|
||||
Desktop,
|
||||
ES,
|
||||
};
|
||||
|
||||
MaybeError Initialize(GetProcAddress getProc);
|
||||
|
||||
bool IsDesktop() const;
|
||||
bool IsES() const;
|
||||
Standard GetStandard() const;
|
||||
uint32_t GetMajor() const;
|
||||
uint32_t GetMinor() const;
|
||||
bool IsAtLeast(uint32_t majorVersion, uint32_t minorVersion) const;
|
||||
|
||||
private:
|
||||
enum class Standard {
|
||||
Desktop,
|
||||
ES,
|
||||
};
|
||||
uint32_t mMajorVersion;
|
||||
uint32_t mMinorVersion;
|
||||
Standard mStandard;
|
||||
|
|
|
@ -30,22 +30,6 @@
|
|||
|
||||
namespace dawn::native::opengl {
|
||||
|
||||
namespace {
|
||||
|
||||
GLenum GLShaderType(SingleShaderStage stage) {
|
||||
switch (stage) {
|
||||
case SingleShaderStage::Vertex:
|
||||
return GL_VERTEX_SHADER;
|
||||
case SingleShaderStage::Fragment:
|
||||
return GL_FRAGMENT_SHADER;
|
||||
case SingleShaderStage::Compute:
|
||||
return GL_COMPUTE_SHADER;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PipelineGL::PipelineGL() : mProgram(0) {}
|
||||
|
||||
PipelineGL::~PipelineGL() = default;
|
||||
|
@ -53,28 +37,6 @@ PipelineGL::~PipelineGL() = default;
|
|||
MaybeError PipelineGL::InitializeBase(const OpenGLFunctions& gl,
|
||||
const PipelineLayout* layout,
|
||||
const PerStage<ProgrammableStage>& stages) {
|
||||
auto CreateShader = [](const OpenGLFunctions& gl, GLenum type,
|
||||
const char* source) -> ResultOrError<GLuint> {
|
||||
GLuint shader = gl.CreateShader(type);
|
||||
gl.ShaderSource(shader, 1, &source, nullptr);
|
||||
gl.CompileShader(shader);
|
||||
|
||||
GLint compileStatus = GL_FALSE;
|
||||
gl.GetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
|
||||
if (compileStatus == GL_FALSE) {
|
||||
GLint infoLogLength = 0;
|
||||
gl.GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
|
||||
if (infoLogLength > 1) {
|
||||
std::vector<char> buffer(infoLogLength);
|
||||
gl.GetShaderInfoLog(shader, infoLogLength, nullptr, &buffer[0]);
|
||||
return DAWN_FORMAT_VALIDATION_ERROR("%s\nProgram compilation failed:\n%s", source,
|
||||
buffer.data());
|
||||
}
|
||||
}
|
||||
return shader;
|
||||
};
|
||||
|
||||
mProgram = gl.CreateProgram();
|
||||
|
||||
// Compute the set of active stages.
|
||||
|
@ -91,12 +53,10 @@ MaybeError PipelineGL::InitializeBase(const OpenGLFunctions& gl,
|
|||
std::vector<GLuint> glShaders;
|
||||
for (SingleShaderStage stage : IterateStages(activeStages)) {
|
||||
const ShaderModule* module = ToBackend(stages[stage].module.Get());
|
||||
std::string glsl;
|
||||
DAWN_TRY_ASSIGN(glsl, module->TranslateToGLSL(stages[stage].entryPoint.c_str(), stage,
|
||||
&combinedSamplers[stage], layout,
|
||||
&needsPlaceholderSampler));
|
||||
GLuint shader;
|
||||
DAWN_TRY_ASSIGN(shader, CreateShader(gl, GLShaderType(stage), glsl.c_str()));
|
||||
DAWN_TRY_ASSIGN(shader,
|
||||
module->CompileShader(gl, stages[stage], stage, &combinedSamplers[stage],
|
||||
layout, &needsPlaceholderSampler));
|
||||
gl.AttachShader(mProgram, shader);
|
||||
glShaders.push_back(shader);
|
||||
}
|
||||
|
|
|
@ -18,14 +18,110 @@
|
|||
#include <utility>
|
||||
|
||||
#include "dawn/native/BindGroupLayout.h"
|
||||
#include "dawn/native/CacheRequest.h"
|
||||
#include "dawn/native/Pipeline.h"
|
||||
#include "dawn/native/TintUtils.h"
|
||||
#include "dawn/native/opengl/DeviceGL.h"
|
||||
#include "dawn/native/opengl/PipelineLayoutGL.h"
|
||||
#include "dawn/native/stream/BlobSource.h"
|
||||
#include "dawn/native/stream/ByteVectorSink.h"
|
||||
#include "dawn/platform/DawnPlatform.h"
|
||||
#include "dawn/platform/tracing/TraceEvent.h"
|
||||
|
||||
#include "tint/tint.h"
|
||||
|
||||
namespace dawn::native {
|
||||
|
||||
namespace {
|
||||
|
||||
GLenum GLShaderType(SingleShaderStage stage) {
|
||||
switch (stage) {
|
||||
case SingleShaderStage::Vertex:
|
||||
return GL_VERTEX_SHADER;
|
||||
case SingleShaderStage::Fragment:
|
||||
return GL_FRAGMENT_SHADER;
|
||||
case SingleShaderStage::Compute:
|
||||
return GL_COMPUTE_SHADER;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
tint::writer::glsl::Version::Standard ToTintGLStandard(opengl::OpenGLVersion::Standard standard) {
|
||||
switch (standard) {
|
||||
case opengl::OpenGLVersion::Standard::Desktop:
|
||||
return tint::writer::glsl::Version::Standard::kDesktop;
|
||||
case opengl::OpenGLVersion::Standard::ES:
|
||||
return tint::writer::glsl::Version::Standard::kES;
|
||||
}
|
||||
}
|
||||
|
||||
using BindingMap = std::unordered_map<tint::sem::BindingPoint, tint::sem::BindingPoint>;
|
||||
|
||||
#define GLSL_COMPILATION_REQUEST_MEMBERS(X) \
|
||||
X(const tint::Program*, inputProgram) \
|
||||
X(std::string, entryPointName) \
|
||||
X(tint::transform::MultiplanarExternalTexture::BindingsMap, externalTextureBindings) \
|
||||
X(BindingMap, glBindings) \
|
||||
X(opengl::OpenGLVersion::Standard, glVersionStandard) \
|
||||
X(uint32_t, glVersionMajor) \
|
||||
X(uint32_t, glVersionMinor)
|
||||
|
||||
DAWN_MAKE_CACHE_REQUEST(GLSLCompilationRequest, GLSL_COMPILATION_REQUEST_MEMBERS);
|
||||
#undef GLSL_COMPILATION_REQUEST_MEMBERS
|
||||
|
||||
#define GLSL_COMPILATION_MEMBERS(X) \
|
||||
X(std::string, glsl) \
|
||||
X(bool, needsPlaceholderSampler) \
|
||||
X(opengl::CombinedSamplerInfo, combinedSamplerInfo)
|
||||
struct GLSLCompilation {
|
||||
DAWN_VISITABLE_MEMBERS(GLSL_COMPILATION_MEMBERS)
|
||||
#undef GLSL_COMPILATION_MEMBERS
|
||||
|
||||
static ResultOrError<GLSLCompilation> FromBlob(Blob blob) {
|
||||
stream::BlobSource source(std::move(blob));
|
||||
GLSLCompilation out;
|
||||
DAWN_TRY(out.VisitAll([&](auto&... members) { return StreamOut(&source, &members...); }));
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
void BlobCache::Store<GLSLCompilation>(const CacheKey& key, const GLSLCompilation& c) {
|
||||
stream::ByteVectorSink sink;
|
||||
c.VisitAll([&](const auto&... members) { StreamIn(&sink, members...); });
|
||||
Store(key, CreateBlob(std::move(sink)));
|
||||
}
|
||||
|
||||
template <>
|
||||
void stream::Stream<opengl::BindingLocation>::Write(
|
||||
stream::Sink* s,
|
||||
const opengl::BindingLocation& bindingLocation) {
|
||||
bindingLocation.VisitAll([&](auto&... members) { return StreamIn(s, members...); });
|
||||
}
|
||||
|
||||
template <>
|
||||
MaybeError stream::Stream<opengl::BindingLocation>::Read(stream::Source* s,
|
||||
opengl::BindingLocation* bindingLocation) {
|
||||
return bindingLocation->VisitAll([&](auto&... members) { return StreamOut(s, &members...); });
|
||||
}
|
||||
|
||||
template <>
|
||||
void stream::Stream<opengl::CombinedSampler>::Write(
|
||||
stream::Sink* s,
|
||||
const opengl::CombinedSampler& combinedSampler) {
|
||||
combinedSampler.VisitAll([&](auto&... members) { return StreamIn(s, members...); });
|
||||
}
|
||||
|
||||
template <>
|
||||
MaybeError stream::Stream<opengl::CombinedSampler>::Read(stream::Source* s,
|
||||
opengl::CombinedSampler* combinedSampler) {
|
||||
return combinedSampler->VisitAll([&](auto&... members) { return StreamOut(s, &members...); });
|
||||
}
|
||||
|
||||
} // namespace dawn::native
|
||||
|
||||
namespace dawn::native::opengl {
|
||||
|
||||
std::string GetBindingName(BindGroupIndex group, BindingNumber bindingNumber) {
|
||||
|
@ -81,104 +177,146 @@ MaybeError ShaderModule::Initialize(ShaderModuleParseResult* parseResult,
|
|||
return {};
|
||||
}
|
||||
|
||||
ResultOrError<std::string> ShaderModule::TranslateToGLSL(const char* entryPointName,
|
||||
SingleShaderStage stage,
|
||||
CombinedSamplerInfo* combinedSamplers,
|
||||
const PipelineLayout* layout,
|
||||
bool* needsPlaceholderSampler) const {
|
||||
ResultOrError<GLuint> ShaderModule::CompileShader(const OpenGLFunctions& gl,
|
||||
const ProgrammableStage& programmableStage,
|
||||
SingleShaderStage stage,
|
||||
CombinedSamplerInfo* combinedSamplers,
|
||||
const PipelineLayout* layout,
|
||||
bool* needsPlaceholderSampler) const {
|
||||
TRACE_EVENT0(GetDevice()->GetPlatform(), General, "TranslateToGLSL");
|
||||
tint::transform::Manager transformManager;
|
||||
tint::transform::DataMap transformInputs;
|
||||
|
||||
auto externalTextureBindings = BuildExternalTextureTransformBindings(layout);
|
||||
if (!externalTextureBindings.empty()) {
|
||||
transformManager.Add<tint::transform::MultiplanarExternalTexture>();
|
||||
transformInputs.Add<tint::transform::MultiplanarExternalTexture::NewBindingPoints>(
|
||||
std::move(externalTextureBindings));
|
||||
}
|
||||
|
||||
tint::Program program;
|
||||
DAWN_TRY_ASSIGN(program, RunTransforms(&transformManager, GetTintProgram(), transformInputs,
|
||||
nullptr, nullptr));
|
||||
const OpenGLVersion& version = ToBackend(GetDevice())->GetGL().GetVersion();
|
||||
|
||||
tint::writer::glsl::Options tintOptions;
|
||||
using Version = tint::writer::glsl::Version;
|
||||
tintOptions.version =
|
||||
Version(version.IsDesktop() ? Version::Standard::kDesktop : Version::Standard::kES,
|
||||
version.GetMajor(), version.GetMinor());
|
||||
|
||||
using tint::transform::BindingPoint;
|
||||
// When textures are accessed without a sampler (e.g., textureLoad()),
|
||||
// GetSamplerTextureUses() will return this sentinel value.
|
||||
BindingPoint placeholderBindingPoint{static_cast<uint32_t>(kMaxBindGroupsTyped), 0};
|
||||
|
||||
tint::inspector::Inspector inspector(&program);
|
||||
// Find all the sampler/texture pairs for this entry point, and create
|
||||
// CombinedSamplers for them. CombinedSampler records the binding points
|
||||
// of the original texture and sampler, and generates a unique name. The
|
||||
// corresponding uniforms will be retrieved by these generated names
|
||||
// in PipelineGL. Any texture-only references will have
|
||||
// "usePlaceholderSampler" set to true, and only the texture binding point
|
||||
// will be used in naming them. In addition, Dawn will bind a
|
||||
// non-filtering sampler for them (see PipelineGL).
|
||||
auto uses = inspector.GetSamplerTextureUses(entryPointName, placeholderBindingPoint);
|
||||
for (const auto& use : uses) {
|
||||
combinedSamplers->emplace_back();
|
||||
|
||||
CombinedSampler* info = &combinedSamplers->back();
|
||||
if (use.sampler_binding_point == placeholderBindingPoint) {
|
||||
info->usePlaceholderSampler = true;
|
||||
*needsPlaceholderSampler = true;
|
||||
} else {
|
||||
info->usePlaceholderSampler = false;
|
||||
}
|
||||
info->samplerLocation.group = BindGroupIndex(use.sampler_binding_point.group);
|
||||
info->samplerLocation.binding = BindingNumber(use.sampler_binding_point.binding);
|
||||
info->textureLocation.group = BindGroupIndex(use.texture_binding_point.group);
|
||||
info->textureLocation.binding = BindingNumber(use.texture_binding_point.binding);
|
||||
tintOptions.binding_map[use] = info->GetName();
|
||||
}
|
||||
if (*needsPlaceholderSampler) {
|
||||
tintOptions.placeholder_binding_point = placeholderBindingPoint;
|
||||
}
|
||||
|
||||
// Since (non-Vulkan) GLSL does not support descriptor sets, generate a
|
||||
// mapping from the original group/binding pair to a binding-only
|
||||
// value. This mapping will be used by Tint to remap all global
|
||||
// variables to the 1D space.
|
||||
const BindingInfoArray& moduleBindingInfo =
|
||||
GetEntryPoint(programmableStage.entryPoint).bindings;
|
||||
std::unordered_map<tint::sem::BindingPoint, tint::sem::BindingPoint> glBindings;
|
||||
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
||||
const BindGroupLayoutBase::BindingMap& bindingMap =
|
||||
layout->GetBindGroupLayout(group)->GetBindingMap();
|
||||
for (const auto& it : bindingMap) {
|
||||
BindingNumber bindingNumber = it.first;
|
||||
BindingIndex bindingIndex = it.second;
|
||||
const BindingInfo& bindingInfo =
|
||||
layout->GetBindGroupLayout(group)->GetBindingInfo(bindingIndex);
|
||||
if (!(bindingInfo.visibility & StageBit(stage))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t shaderIndex = layout->GetBindingIndexInfo()[group][bindingIndex];
|
||||
const BindGroupLayoutBase* bgl = layout->GetBindGroupLayout(group);
|
||||
const auto& groupBindingInfo = moduleBindingInfo[group];
|
||||
for (const auto& [bindingNumber, bindingInfo] : groupBindingInfo) {
|
||||
BindingIndex bindingIndex = bgl->GetBindingIndex(bindingNumber);
|
||||
GLuint shaderIndex = layout->GetBindingIndexInfo()[group][bindingIndex];
|
||||
BindingPoint srcBindingPoint{static_cast<uint32_t>(group),
|
||||
static_cast<uint32_t>(bindingNumber)};
|
||||
BindingPoint dstBindingPoint{0, shaderIndex};
|
||||
tintOptions.binding_points.emplace(srcBindingPoint, dstBindingPoint);
|
||||
if (srcBindingPoint != dstBindingPoint) {
|
||||
glBindings.emplace(srcBindingPoint, dstBindingPoint);
|
||||
}
|
||||
}
|
||||
tintOptions.allow_collisions = true;
|
||||
}
|
||||
auto result = tint::writer::glsl::Generate(&program, tintOptions, entryPointName);
|
||||
DAWN_INVALID_IF(!result.success, "An error occured while generating GLSL: %s.", result.error);
|
||||
std::string glsl = std::move(result.glsl);
|
||||
|
||||
GLSLCompilationRequest req = {};
|
||||
req.inputProgram = GetTintProgram();
|
||||
req.entryPointName = programmableStage.entryPoint;
|
||||
req.externalTextureBindings = BuildExternalTextureTransformBindings(layout);
|
||||
req.glBindings = std::move(glBindings);
|
||||
req.glVersionStandard = version.GetStandard();
|
||||
req.glVersionMajor = version.GetMajor();
|
||||
req.glVersionMinor = version.GetMinor();
|
||||
|
||||
CacheResult<GLSLCompilation> compilationResult;
|
||||
DAWN_TRY_LOAD_OR_RUN(
|
||||
compilationResult, GetDevice(), std::move(req), GLSLCompilation::FromBlob,
|
||||
[](GLSLCompilationRequest r) -> ResultOrError<GLSLCompilation> {
|
||||
tint::transform::Manager transformManager;
|
||||
tint::transform::DataMap transformInputs;
|
||||
|
||||
if (!r.externalTextureBindings.empty()) {
|
||||
transformManager.Add<tint::transform::MultiplanarExternalTexture>();
|
||||
transformInputs.Add<tint::transform::MultiplanarExternalTexture::NewBindingPoints>(
|
||||
std::move(r.externalTextureBindings));
|
||||
}
|
||||
|
||||
tint::Program program;
|
||||
DAWN_TRY_ASSIGN(program, RunTransforms(&transformManager, r.inputProgram,
|
||||
transformInputs, nullptr, nullptr));
|
||||
|
||||
tint::writer::glsl::Options tintOptions;
|
||||
tintOptions.version = tint::writer::glsl::Version(ToTintGLStandard(r.glVersionStandard),
|
||||
r.glVersionMajor, r.glVersionMinor);
|
||||
|
||||
// When textures are accessed without a sampler (e.g., textureLoad()),
|
||||
// GetSamplerTextureUses() will return this sentinel value.
|
||||
BindingPoint placeholderBindingPoint{static_cast<uint32_t>(kMaxBindGroupsTyped), 0};
|
||||
|
||||
bool needsPlaceholderSampler = false;
|
||||
tint::inspector::Inspector inspector(&program);
|
||||
// Find all the sampler/texture pairs for this entry point, and create
|
||||
// CombinedSamplers for them. CombinedSampler records the binding points
|
||||
// of the original texture and sampler, and generates a unique name. The
|
||||
// corresponding uniforms will be retrieved by these generated names
|
||||
// in PipelineGL. Any texture-only references will have
|
||||
// "usePlaceholderSampler" set to true, and only the texture binding point
|
||||
// will be used in naming them. In addition, Dawn will bind a
|
||||
// non-filtering sampler for them (see PipelineGL).
|
||||
auto uses = inspector.GetSamplerTextureUses(r.entryPointName, placeholderBindingPoint);
|
||||
CombinedSamplerInfo combinedSamplerInfo;
|
||||
for (const auto& use : uses) {
|
||||
combinedSamplerInfo.emplace_back();
|
||||
|
||||
CombinedSampler* info = &combinedSamplerInfo.back();
|
||||
if (use.sampler_binding_point == placeholderBindingPoint) {
|
||||
info->usePlaceholderSampler = true;
|
||||
needsPlaceholderSampler = true;
|
||||
tintOptions.placeholder_binding_point = placeholderBindingPoint;
|
||||
} else {
|
||||
info->usePlaceholderSampler = false;
|
||||
}
|
||||
info->samplerLocation.group = BindGroupIndex(use.sampler_binding_point.group);
|
||||
info->samplerLocation.binding = BindingNumber(use.sampler_binding_point.binding);
|
||||
info->textureLocation.group = BindGroupIndex(use.texture_binding_point.group);
|
||||
info->textureLocation.binding = BindingNumber(use.texture_binding_point.binding);
|
||||
tintOptions.binding_map[use] = info->GetName();
|
||||
}
|
||||
tintOptions.binding_points = std::move(r.glBindings);
|
||||
tintOptions.allow_collisions = true;
|
||||
|
||||
auto result = tint::writer::glsl::Generate(&program, tintOptions, r.entryPointName);
|
||||
DAWN_INVALID_IF(!result.success, "An error occured while generating GLSL: %s.",
|
||||
result.error);
|
||||
|
||||
return GLSLCompilation{std::move(result.glsl), needsPlaceholderSampler,
|
||||
std::move(combinedSamplerInfo)};
|
||||
});
|
||||
|
||||
if (GetDevice()->IsToggleEnabled(Toggle::DumpShaders)) {
|
||||
std::ostringstream dumpedMsg;
|
||||
dumpedMsg << "/* Dumped generated GLSL */" << std::endl << glsl;
|
||||
dumpedMsg << "/* Dumped generated GLSL */" << std::endl << compilationResult->glsl;
|
||||
|
||||
GetDevice()->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
|
||||
}
|
||||
|
||||
return glsl;
|
||||
GLuint shader = gl.CreateShader(GLShaderType(stage));
|
||||
const char* source = compilationResult->glsl.c_str();
|
||||
gl.ShaderSource(shader, 1, &source, nullptr);
|
||||
gl.CompileShader(shader);
|
||||
|
||||
GLint compileStatus = GL_FALSE;
|
||||
gl.GetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
|
||||
if (compileStatus == GL_FALSE) {
|
||||
GLint infoLogLength = 0;
|
||||
gl.GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
|
||||
if (infoLogLength > 1) {
|
||||
std::vector<char> buffer(infoLogLength);
|
||||
gl.GetShaderInfoLog(shader, infoLogLength, nullptr, &buffer[0]);
|
||||
gl.DeleteShader(shader);
|
||||
return DAWN_FORMAT_VALIDATION_ERROR("%s\nProgram compilation failed:\n%s", source,
|
||||
buffer.data());
|
||||
}
|
||||
}
|
||||
|
||||
if (BlobCache* cache = GetDevice()->GetBlobCache()) {
|
||||
cache->EnsureStored(compilationResult);
|
||||
}
|
||||
*needsPlaceholderSampler = compilationResult->needsPlaceholderSampler;
|
||||
*combinedSamplers = std::move(compilationResult->combinedSamplerInfo);
|
||||
return shader;
|
||||
}
|
||||
|
||||
} // namespace dawn::native::opengl
|
||||
|
|
|
@ -21,37 +21,53 @@
|
|||
#include <vector>
|
||||
|
||||
#include "dawn/native/ShaderModule.h"
|
||||
|
||||
#include "dawn/native/VisitableMembers.h"
|
||||
#include "dawn/native/opengl/opengl_platform.h"
|
||||
|
||||
namespace dawn::native::opengl {
|
||||
namespace dawn::native {
|
||||
|
||||
struct ProgrammableStage;
|
||||
|
||||
namespace stream {
|
||||
class Sink;
|
||||
class Source;
|
||||
} // namespace stream
|
||||
|
||||
namespace opengl {
|
||||
|
||||
class Device;
|
||||
class PipelineLayout;
|
||||
struct OpenGLFunctions;
|
||||
|
||||
std::string GetBindingName(BindGroupIndex group, BindingNumber bindingNumber);
|
||||
|
||||
#define BINDING_LOCATION_MEMBERS(X) \
|
||||
X(BindGroupIndex, group) \
|
||||
X(BindingNumber, binding)
|
||||
struct BindingLocation {
|
||||
BindGroupIndex group;
|
||||
BindingNumber binding;
|
||||
DAWN_VISITABLE_MEMBERS(BINDING_LOCATION_MEMBERS)
|
||||
#undef BINDING_LOCATION_MEMBERS
|
||||
};
|
||||
bool operator<(const BindingLocation& a, const BindingLocation& b);
|
||||
|
||||
#define COMBINED_SAMPLER_MEMBERS(X) \
|
||||
X(BindingLocation, samplerLocation) \
|
||||
X(BindingLocation, textureLocation) \
|
||||
/* OpenGL requires a sampler with texelFetch. If this is true, the developer did not */ \
|
||||
/* provide one and Dawn should bind a placeholder non-filtering sampler; */ \
|
||||
/* |samplerLocation| is unused. */ \
|
||||
X(bool, usePlaceholderSampler)
|
||||
|
||||
struct CombinedSampler {
|
||||
BindingLocation samplerLocation;
|
||||
BindingLocation textureLocation;
|
||||
// OpenGL requires a sampler with texelFetch. If this is true, the developer did not provide
|
||||
// one and Dawn should bind a placeholder non-filtering sampler. |samplerLocation| is
|
||||
// unused.
|
||||
bool usePlaceholderSampler;
|
||||
DAWN_VISITABLE_MEMBERS(COMBINED_SAMPLER_MEMBERS)
|
||||
#undef COMBINED_SAMPLER_MEMBERS
|
||||
|
||||
std::string GetName() const;
|
||||
};
|
||||
bool operator<(const CombinedSampler& a, const CombinedSampler& b);
|
||||
|
||||
using CombinedSamplerInfo = std::vector<CombinedSampler>;
|
||||
|
||||
using BindingInfoArrayTable = std::unordered_map<std::string, std::unique_ptr<BindingInfoArray>>;
|
||||
|
||||
class ShaderModule final : public ShaderModuleBase {
|
||||
public:
|
||||
static ResultOrError<Ref<ShaderModule>> Create(Device* device,
|
||||
|
@ -59,11 +75,12 @@ class ShaderModule final : public ShaderModuleBase {
|
|||
ShaderModuleParseResult* parseResult,
|
||||
OwnedCompilationMessages* compilationMessages);
|
||||
|
||||
ResultOrError<std::string> TranslateToGLSL(const char* entryPointName,
|
||||
SingleShaderStage stage,
|
||||
CombinedSamplerInfo* combinedSamplers,
|
||||
const PipelineLayout* layout,
|
||||
bool* needsPlaceholderSampler) const;
|
||||
ResultOrError<GLuint> CompileShader(const OpenGLFunctions& gl,
|
||||
const ProgrammableStage& programmableStage,
|
||||
SingleShaderStage stage,
|
||||
CombinedSamplerInfo* combinedSamplers,
|
||||
const PipelineLayout* layout,
|
||||
bool* needsPlaceholderSampler) const;
|
||||
|
||||
private:
|
||||
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
|
||||
|
@ -72,6 +89,7 @@ class ShaderModule final : public ShaderModuleBase {
|
|||
OwnedCompilationMessages* compilationMessages);
|
||||
};
|
||||
|
||||
} // namespace dawn::native::opengl
|
||||
} // namespace opengl
|
||||
} // namespace dawn::native
|
||||
|
||||
#endif // SRC_DAWN_NATIVE_OPENGL_SHADERMODULEGL_H_
|
||||
|
|
|
@ -108,8 +108,8 @@ class PipelineCachingTests : public DawnTest {
|
|||
const EntryCounts counts = {
|
||||
// pipeline caching is only implemented on D3D12/Vulkan
|
||||
IsD3D12() || IsVulkan() ? 1u : 0u,
|
||||
// shader module caching is only implemented on Vulkan/D3D12/Metal
|
||||
IsVulkan() || IsMetal() || IsD3D12() ? 1u : 0u,
|
||||
// One blob per shader module
|
||||
1u,
|
||||
};
|
||||
NiceMock<CachingInterfaceMock> mMockCache;
|
||||
};
|
||||
|
@ -587,8 +587,8 @@ TEST_P(SinglePipelineCachingTests, RenderPipelineBlobCacheLayout) {
|
|||
}
|
||||
|
||||
// Cache should not hit for the fragment shader, but should hit for the pipeline.
|
||||
// Except for D3D12, the shader is different but compiles to the same due to binding number
|
||||
// remapping.
|
||||
// On Metal and Vulkan, the shader is different but compiles to the same due to binding number
|
||||
// remapping. On other backends, the compiled shader is different and so is the pipeline.
|
||||
{
|
||||
wgpu::Device device = CreateDevice();
|
||||
utils::ComboRenderPipelineDescriptor desc;
|
||||
|
@ -605,7 +605,7 @@ TEST_P(SinglePipelineCachingTests, RenderPipelineBlobCacheLayout) {
|
|||
{1, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Uniform},
|
||||
}),
|
||||
});
|
||||
if (!IsD3D12()) {
|
||||
if (IsMetal() || IsVulkan()) {
|
||||
EXPECT_CACHE_STATS(mMockCache, Hit(counts.shaderModule + counts.pipeline),
|
||||
Add(counts.shaderModule), device.CreateRenderPipeline(&desc));
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue