Add Overrides implementation for OpenGL/OpenGLES backend

As we are using SubstituteOverride, it is easy to add
overridable constants support for OpenGL/OpenGLES.

Also add validate workgroup size for null backend.

Bug: dawn:1537, dawn:1504
Change-Id: I293f10b9a6c606aee6c0ed25b1d966bc56a0b88d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101800
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Shrek Shao <shrekshao@google.com>
This commit is contained in:
shrekshao 2022-09-09 00:49:08 +00:00 committed by Dawn LUCI CQ
parent 7edef20bdd
commit 14579b9da3
8 changed files with 92 additions and 35 deletions

View File

@ -327,8 +327,8 @@ ResultOrError<std::string> TranslateToHLSL(
} }
if (r.substituteOverrideConfig) { if (r.substituteOverrideConfig) {
// This needs to run after SingleEntryPoint transform to get rid of overrides not used for // This needs to run after SingleEntryPoint transform which removes unused overrides for
// the current entry point. // current entry point.
transformManager.Add<tint::transform::SubstituteOverride>(); transformManager.Add<tint::transform::SubstituteOverride>();
transformInputs.Add<tint::transform::SubstituteOverride::Config>( transformInputs.Add<tint::transform::SubstituteOverride::Config>(
std::move(r.substituteOverrideConfig).value()); std::move(r.substituteOverrideConfig).value());

View File

@ -206,8 +206,8 @@ ResultOrError<CacheResult<MslCompilation>> TranslateToMSL(
} }
if (r.substituteOverrideConfig) { if (r.substituteOverrideConfig) {
// This needs to run after SingleEntryPoint transform to get rid of overrides not // This needs to run after SingleEntryPoint transform which removes unused overrides
// used for the current entry point. // for current entry point.
transformManager.Add<tint::transform::SubstituteOverride>(); transformManager.Add<tint::transform::SubstituteOverride>();
transformInputs.Add<tint::transform::SubstituteOverride::Config>( transformInputs.Add<tint::transform::SubstituteOverride::Config>(
std::move(r.substituteOverrideConfig).value()); std::move(r.substituteOverrideConfig).value());

View File

@ -22,6 +22,9 @@
#include "dawn/native/ErrorData.h" #include "dawn/native/ErrorData.h"
#include "dawn/native/Instance.h" #include "dawn/native/Instance.h"
#include "dawn/native/Surface.h" #include "dawn/native/Surface.h"
#include "dawn/native/TintUtils.h"
#include "tint/tint.h"
namespace dawn::native::null { namespace dawn::native::null {
@ -383,6 +386,40 @@ MaybeError Queue::WriteBufferImpl(BufferBase* buffer,
// ComputePipeline // ComputePipeline
MaybeError ComputePipeline::Initialize() { MaybeError ComputePipeline::Initialize() {
const ProgrammableStage& computeStage = GetStage(SingleShaderStage::Compute);
tint::Program transformedProgram;
const tint::Program* program;
if (!computeStage.metadata->overrides.empty()) {
tint::transform::Manager transformManager;
tint::transform::DataMap transformInputs;
transformManager.Add<tint::transform::SingleEntryPoint>();
transformInputs.Add<tint::transform::SingleEntryPoint::Config>(
computeStage.entryPoint.c_str());
// This needs to run after SingleEntryPoint transform which removes unused overrides for
// current entry point.
transformManager.Add<tint::transform::SubstituteOverride>();
transformInputs.Add<tint::transform::SubstituteOverride::Config>(
BuildSubstituteOverridesTransformConfig(computeStage));
DAWN_TRY_ASSIGN(transformedProgram,
RunTransforms(&transformManager, computeStage.module->GetTintProgram(),
transformInputs, nullptr, nullptr));
program = &transformedProgram;
} else {
program = computeStage.module->GetTintProgram();
}
// Do the workgroup size validation as it is actually backend agnostic.
const CombinedLimits& limits = GetDevice()->GetLimits();
Extent3D _;
DAWN_TRY_ASSIGN(
_, ValidateComputeStageWorkgroupSize(*program, computeStage.entryPoint.c_str(),
LimitsForCompilationRequest::Create(limits.v1)));
return {}; return {};
} }

View File

@ -60,8 +60,11 @@ using BindingMap = std::unordered_map<tint::sem::BindingPoint, tint::sem::Bindin
#define GLSL_COMPILATION_REQUEST_MEMBERS(X) \ #define GLSL_COMPILATION_REQUEST_MEMBERS(X) \
X(const tint::Program*, inputProgram) \ X(const tint::Program*, inputProgram) \
X(std::string, entryPointName) \ X(std::string, entryPointName) \
X(SingleShaderStage, stage) \
X(tint::transform::MultiplanarExternalTexture::BindingsMap, externalTextureBindings) \ X(tint::transform::MultiplanarExternalTexture::BindingsMap, externalTextureBindings) \
X(BindingMap, glBindings) \ X(BindingMap, glBindings) \
X(std::optional<tint::transform::SubstituteOverride::Config>, substituteOverrideConfig) \
X(LimitsForCompilationRequest, limits) \
X(opengl::OpenGLVersion::Standard, glVersionStandard) \ X(opengl::OpenGLVersion::Standard, glVersionStandard) \
X(uint32_t, glVersionMajor) \ X(uint32_t, glVersionMajor) \
X(uint32_t, glVersionMinor) X(uint32_t, glVersionMinor)
@ -168,11 +171,21 @@ ResultOrError<GLuint> ShaderModule::CompileShader(const OpenGLFunctions& gl,
} }
} }
std::optional<tint::transform::SubstituteOverride::Config> substituteOverrideConfig;
if (!programmableStage.metadata->overrides.empty()) {
substituteOverrideConfig = BuildSubstituteOverridesTransformConfig(programmableStage);
}
const CombinedLimits& limits = GetDevice()->GetLimits();
GLSLCompilationRequest req = {}; GLSLCompilationRequest req = {};
req.inputProgram = GetTintProgram(); req.inputProgram = GetTintProgram();
req.stage = stage;
req.entryPointName = programmableStage.entryPoint; req.entryPointName = programmableStage.entryPoint;
req.externalTextureBindings = BuildExternalTextureTransformBindings(layout); req.externalTextureBindings = BuildExternalTextureTransformBindings(layout);
req.glBindings = std::move(glBindings); req.glBindings = std::move(glBindings);
req.substituteOverrideConfig = std::move(substituteOverrideConfig);
req.limits = LimitsForCompilationRequest::Create(limits.v1);
req.glVersionStandard = version.GetStandard(); req.glVersionStandard = version.GetStandard();
req.glVersionMajor = version.GetMajor(); req.glVersionMajor = version.GetMajor();
req.glVersionMinor = version.GetMinor(); req.glVersionMinor = version.GetMinor();
@ -190,10 +203,27 @@ ResultOrError<GLuint> ShaderModule::CompileShader(const OpenGLFunctions& gl,
std::move(r.externalTextureBindings)); std::move(r.externalTextureBindings));
} }
if (r.substituteOverrideConfig) {
transformManager.Add<tint::transform::SingleEntryPoint>();
transformInputs.Add<tint::transform::SingleEntryPoint::Config>(r.entryPointName);
// This needs to run after SingleEntryPoint transform which removes unused overrides
// for current entry point.
transformManager.Add<tint::transform::SubstituteOverride>();
transformInputs.Add<tint::transform::SubstituteOverride::Config>(
std::move(r.substituteOverrideConfig).value());
}
tint::Program program; tint::Program program;
DAWN_TRY_ASSIGN(program, RunTransforms(&transformManager, r.inputProgram, DAWN_TRY_ASSIGN(program, RunTransforms(&transformManager, r.inputProgram,
transformInputs, nullptr, nullptr)); transformInputs, nullptr, nullptr));
if (r.stage == SingleShaderStage::Compute) {
// Validate workgroup size after program runs transforms.
Extent3D _;
DAWN_TRY_ASSIGN(_, ValidateComputeStageWorkgroupSize(
program, r.entryPointName.c_str(), r.limits));
}
tint::writer::glsl::Options tintOptions; tint::writer::glsl::Options tintOptions;
tintOptions.version = tint::writer::glsl::Version(ToTintGLStandard(r.glVersionStandard), tintOptions.version = tint::writer::glsl::Version(ToTintGLStandard(r.glVersionStandard),
r.glVersionMajor, r.glVersionMinor); r.glVersionMajor, r.glVersionMinor);

View File

@ -311,8 +311,8 @@ ResultOrError<ShaderModule::ModuleAndSpirv> ShaderModule::GetHandleAndSpirv(
r.newBindingsMap); r.newBindingsMap);
} }
if (r.substituteOverrideConfig) { if (r.substituteOverrideConfig) {
// This needs to run after SingleEntryPoint transform to get rid of overrides not // This needs to run after SingleEntryPoint transform which removes unused overrides
// used for the current entry point. // for current entry point.
transformManager.Add<tint::transform::SubstituteOverride>(); transformManager.Add<tint::transform::SubstituteOverride>();
transformInputs.Add<tint::transform::SubstituteOverride::Config>( transformInputs.Add<tint::transform::SubstituteOverride::Config>(
std::move(r.substituteOverrideConfig).value()); std::move(r.substituteOverrideConfig).value());

View File

@ -395,9 +395,6 @@ fn main(@location(0) pos : vec4<f32>) -> @builtin(position) vec4<f32> {
// Test overridable constants without numeric identifiers // Test overridable constants without numeric identifiers
TEST_P(ShaderTests, OverridableConstants) { TEST_P(ShaderTests, OverridableConstants) {
DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
uint32_t const kCount = 11; uint32_t const kCount = 11;
std::vector<uint32_t> expected(kCount); std::vector<uint32_t> expected(kCount);
std::iota(expected.begin(), expected.end(), 0); std::iota(expected.begin(), expected.end(), 0);
@ -473,9 +470,6 @@ struct Buf {
// Test one shader shared by two pipelines with different constants overridden // Test one shader shared by two pipelines with different constants overridden
TEST_P(ShaderTests, OverridableConstantsSharedShader) { TEST_P(ShaderTests, OverridableConstantsSharedShader) {
DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
std::vector<uint32_t> expected1{1}; std::vector<uint32_t> expected1{1};
wgpu::Buffer buffer1 = CreateBuffer(expected1.size()); wgpu::Buffer buffer1 = CreateBuffer(expected1.size());
std::vector<uint32_t> expected2{2}; std::vector<uint32_t> expected2{2};
@ -530,9 +524,6 @@ struct Buf {
// Test overridable constants work with workgroup size // Test overridable constants work with workgroup size
TEST_P(ShaderTests, OverridableConstantsWorkgroupSize) { TEST_P(ShaderTests, OverridableConstantsWorkgroupSize) {
DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
std::string shader = R"( std::string shader = R"(
override x: u32; override x: u32;
@ -594,9 +585,6 @@ struct Buf {
// Test overridable constants with numeric identifiers // Test overridable constants with numeric identifiers
TEST_P(ShaderTests, OverridableConstantsNumericIdentifiers) { TEST_P(ShaderTests, OverridableConstantsNumericIdentifiers) {
DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
uint32_t const kCount = 4; uint32_t const kCount = 4;
std::vector<uint32_t> expected{1u, 2u, 3u, 0u}; std::vector<uint32_t> expected{1u, 2u, 3u, 0u};
wgpu::Buffer buffer = CreateBuffer(kCount); wgpu::Buffer buffer = CreateBuffer(kCount);
@ -651,9 +639,6 @@ struct Buf {
// Test overridable constants precision // Test overridable constants precision
// D3D12 HLSL shader uses defines so we want float number to have enough precision // D3D12 HLSL shader uses defines so we want float number to have enough precision
TEST_P(ShaderTests, OverridableConstantsPrecision) { TEST_P(ShaderTests, OverridableConstantsPrecision) {
DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
uint32_t const kCount = 2; uint32_t const kCount = 2;
float const kValue1 = 3.14159; float const kValue1 = 3.14159;
float const kValue2 = 3.141592653589793238; float const kValue2 = 3.141592653589793238;
@ -702,9 +687,6 @@ struct Buf {
// Test overridable constants for different entry points // Test overridable constants for different entry points
TEST_P(ShaderTests, OverridableConstantsMultipleEntryPoints) { TEST_P(ShaderTests, OverridableConstantsMultipleEntryPoints) {
DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
uint32_t const kCount = 1; uint32_t const kCount = 1;
std::vector<uint32_t> expected1{1u}; std::vector<uint32_t> expected1{1u};
std::vector<uint32_t> expected2{2u}; std::vector<uint32_t> expected2{2u};
@ -807,9 +789,6 @@ struct Buf {
// Draw a triangle covering the render target, with vertex position and color values from // Draw a triangle covering the render target, with vertex position and color values from
// overridable constants // overridable constants
TEST_P(ShaderTests, OverridableConstantsRenderPipeline) { TEST_P(ShaderTests, OverridableConstantsRenderPipeline) {
DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"( wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
@id(1111) override xright: f32; @id(1111) override xright: f32;
@id(2222) override ytop: f32; @id(2222) override ytop: f32;

View File

@ -392,4 +392,10 @@ TEST_P(WorkgroupSizeValidationTest, DISABLED_ValidationAfterOverrideStorageSize)
CheckPipelineWithWorkgroupStorage(false, 0, maxMat4Count + 1); CheckPipelineWithWorkgroupStorage(false, 0, maxMat4Count + 1);
} }
DAWN_INSTANTIATE_TEST(WorkgroupSizeValidationTest, D3D12Backend(), MetalBackend(), VulkanBackend()); DAWN_INSTANTIATE_TEST(WorkgroupSizeValidationTest,
D3D12Backend(),
MetalBackend(),
NullBackend(),
OpenGLBackend(),
OpenGLESBackend(),
VulkanBackend());

View File

@ -119,6 +119,11 @@ TEST_F(ComputePipelineOverridableConstantsValidationTest, ConstantsIdentifierLoo
std::vector<wgpu::ConstantEntry> constants{{nullptr, "1000", 0}}; std::vector<wgpu::ConstantEntry> constants{{nullptr, "1000", 0}};
TestCreatePipeline(constants); TestCreatePipeline(constants);
} }
{
// Error: c10 already has a constant numeric id specified
std::vector<wgpu::ConstantEntry> constants{{nullptr, "c10", 0}};
ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
}
{ {
// Error: constant numeric id not specified // Error: constant numeric id not specified
std::vector<wgpu::ConstantEntry> constants{{nullptr, "9999", 0}}; std::vector<wgpu::ConstantEntry> constants{{nullptr, "9999", 0}};