Add support for Tint's HLSL writer as a Toggle

This commit adds a Toggle that switches SPIRV-cross's HLSL generator for
Tint's HLSL writer. New Toggle currently defaults to false.

Bug: dawn:548
Change-Id: I37e238c6ba887efd65727809c8a6919df515a35e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/31640
Reviewed-by: Bryan Bernhart <bryan.bernhart@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: Enrico Galli <enrico.galli@intel.com>
This commit is contained in:
Enrico Galli 2020-11-05 18:52:49 +00:00 committed by Commit Bot service account
parent c1dbb2625b
commit 2b6b0f45ff
10 changed files with 131 additions and 23 deletions

View File

@ -138,7 +138,10 @@ namespace dawn_native {
{"disallow_unsafe_apis", {"disallow_unsafe_apis",
"Produces validation errors on API entry points or parameter combinations that " "Produces validation errors on API entry points or parameter combinations that "
"aren't considered secure yet.", "aren't considered secure yet.",
"http://crbug.com/1138528"}} "http://crbug.com/1138528"}},
{Toggle::UseTintGenerator,
{"use_tint_generator", "Use Tint instead of SPRIV-cross to generate shaders.",
"https://crbug.com/dawn/548"}},
// Dummy comment to separate the }} so it is clearer what to copy-paste to add a toggle. // Dummy comment to separate the }} so it is clearer what to copy-paste to add a toggle.
}}; }};

View File

@ -44,6 +44,7 @@ namespace dawn_native {
DisableRobustness, DisableRobustness,
MetalEnableVertexPulling, MetalEnableVertexPulling,
DisallowUnsafeAPIs, DisallowUnsafeAPIs,
UseTintGenerator,
EnumCount, EnumCount,
InvalidEnum = EnumCount, InvalidEnum = EnumCount,

View File

@ -43,27 +43,37 @@ namespace dawn_native { namespace d3d12 {
ShaderModule* module = ToBackend(descriptor->computeStage.module); ShaderModule* module = ToBackend(descriptor->computeStage.module);
// Note that the HLSL will always use entryPoint "main". const char* entryPoint = descriptor->computeStage.entryPoint;
std::string hlslSource; std::string hlslSource;
DAWN_TRY_ASSIGN(hlslSource, module->TranslateToHLSL(descriptor->computeStage.entryPoint, if (device->IsToggleEnabled(Toggle::UseTintGenerator)) {
SingleShaderStage::Compute, DAWN_TRY_ASSIGN(hlslSource,
module->TranslateToHLSLWithTint(entryPoint, SingleShaderStage::Compute,
ToBackend(GetLayout()))); ToBackend(GetLayout())));
} else {
DAWN_TRY_ASSIGN(hlslSource,
module->TranslateToHLSLWithSPIRVCross(
entryPoint, SingleShaderStage::Compute, ToBackend(GetLayout())));
// Note that the HLSL will always use entryPoint "main" under SPIRV-cross.
entryPoint = "main";
}
D3D12_COMPUTE_PIPELINE_STATE_DESC d3dDesc = {}; D3D12_COMPUTE_PIPELINE_STATE_DESC d3dDesc = {};
d3dDesc.pRootSignature = ToBackend(GetLayout())->GetRootSignature(); d3dDesc.pRootSignature = ToBackend(GetLayout())->GetRootSignature();
ComPtr<IDxcBlob> compiledDXCShader; ComPtr<IDxcBlob> compiledDXCShader;
ComPtr<ID3DBlob> compiledFXCShader; ComPtr<ID3DBlob> compiledFXCShader;
if (device->IsToggleEnabled(Toggle::UseDXC)) { if (device->IsToggleEnabled(Toggle::UseDXC)) {
DAWN_TRY_ASSIGN(compiledDXCShader, CompileShaderDXC(device, SingleShaderStage::Compute, DAWN_TRY_ASSIGN(compiledDXCShader,
hlslSource, "main", compileFlags)); CompileShaderDXC(device, SingleShaderStage::Compute, hlslSource,
entryPoint, compileFlags));
d3dDesc.CS.pShaderBytecode = compiledDXCShader->GetBufferPointer(); d3dDesc.CS.pShaderBytecode = compiledDXCShader->GetBufferPointer();
d3dDesc.CS.BytecodeLength = compiledDXCShader->GetBufferSize(); d3dDesc.CS.BytecodeLength = compiledDXCShader->GetBufferSize();
} else { } else {
DAWN_TRY_ASSIGN(compiledFXCShader, CompileShaderFXC(device, SingleShaderStage::Compute, DAWN_TRY_ASSIGN(compiledFXCShader,
hlslSource, "main", compileFlags)); CompileShaderFXC(device, SingleShaderStage::Compute, hlslSource,
entryPoint, compileFlags));
d3dDesc.CS.pShaderBytecode = compiledFXCShader->GetBufferPointer(); d3dDesc.CS.pShaderBytecode = compiledFXCShader->GetBufferPointer();
d3dDesc.CS.BytecodeLength = compiledFXCShader->GetBufferSize(); d3dDesc.CS.BytecodeLength = compiledFXCShader->GetBufferSize();
} }

View File

@ -499,6 +499,7 @@ namespace dawn_native { namespace d3d12 {
SetToggle(Toggle::UseD3D12RenderPass, GetDeviceInfo().supportsRenderPass); SetToggle(Toggle::UseD3D12RenderPass, GetDeviceInfo().supportsRenderPass);
SetToggle(Toggle::UseD3D12ResidencyManagement, true); SetToggle(Toggle::UseD3D12ResidencyManagement, true);
SetToggle(Toggle::UseDXC, false); SetToggle(Toggle::UseDXC, false);
SetToggle(Toggle::UseTintGenerator, false);
// By default use the maximum shader-visible heap size allowed. // By default use the maximum shader-visible heap size allowed.
SetToggle(Toggle::UseD3D12SmallShaderVisibleHeapForTesting, false); SetToggle(Toggle::UseD3D12SmallShaderVisibleHeapForTesting, false);

View File

@ -311,21 +311,32 @@ namespace dawn_native { namespace d3d12 {
wgpu::ShaderStage renderStages = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment; wgpu::ShaderStage renderStages = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment;
for (auto stage : IterateStages(renderStages)) { for (auto stage : IterateStages(renderStages)) {
// Note that the HLSL entryPoint will always be "main".
std::string hlslSource; std::string hlslSource;
DAWN_TRY_ASSIGN(hlslSource, const char* entryPoint = GetStage(stage).entryPoint.c_str();
modules[stage]->TranslateToHLSL(GetStage(stage).entryPoint.c_str(),
stage, ToBackend(GetLayout()))); if (device->IsToggleEnabled(Toggle::UseTintGenerator)) {
DAWN_TRY_ASSIGN(hlslSource, modules[stage]->TranslateToHLSLWithTint(
entryPoint, stage, ToBackend(GetLayout())));
} else {
DAWN_TRY_ASSIGN(hlslSource, modules[stage]->TranslateToHLSLWithSPIRVCross(
entryPoint, stage, ToBackend(GetLayout())));
// Note that the HLSL will always use entryPoint "main" under SPIRV-cross.
entryPoint = "main";
}
if (device->IsToggleEnabled(Toggle::UseDXC)) { if (device->IsToggleEnabled(Toggle::UseDXC)) {
DAWN_TRY_ASSIGN(compiledDXCShader[stage], DAWN_TRY_ASSIGN(
CompileShaderDXC(device, stage, hlslSource, "main", compileFlags)); compiledDXCShader[stage],
CompileShaderDXC(device, stage, hlslSource, entryPoint, compileFlags));
shaders[stage]->pShaderBytecode = compiledDXCShader[stage]->GetBufferPointer(); shaders[stage]->pShaderBytecode = compiledDXCShader[stage]->GetBufferPointer();
shaders[stage]->BytecodeLength = compiledDXCShader[stage]->GetBufferSize(); shaders[stage]->BytecodeLength = compiledDXCShader[stage]->GetBufferSize();
} else { } else {
DAWN_TRY_ASSIGN(compiledFXCShader[stage], DAWN_TRY_ASSIGN(
CompileShaderFXC(device, stage, hlslSource, "main", compileFlags)); compiledFXCShader[stage],
CompileShaderFXC(device, stage, hlslSource, entryPoint, compileFlags));
shaders[stage]->pShaderBytecode = compiledFXCShader[stage]->GetBufferPointer(); shaders[stage]->pShaderBytecode = compiledFXCShader[stage]->GetBufferPointer();
shaders[stage]->BytecodeLength = compiledFXCShader[stage]->GetBufferSize(); shaders[stage]->BytecodeLength = compiledFXCShader[stage]->GetBufferSize();

View File

@ -29,6 +29,10 @@
#include <spirv_hlsl.hpp> #include <spirv_hlsl.hpp>
#ifdef DAWN_ENABLE_WGSL
# include <tint/tint.h>
#endif // DAWN_ENABLE_WGSL
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
namespace { namespace {
@ -176,10 +180,68 @@ namespace dawn_native { namespace d3d12 {
: ShaderModuleBase(device, descriptor) { : ShaderModuleBase(device, descriptor) {
} }
ResultOrError<std::string> ShaderModule::TranslateToHLSL(const char* entryPointName, ResultOrError<std::string> ShaderModule::TranslateToHLSLWithTint(const char* entryPointName,
SingleShaderStage stage, SingleShaderStage stage,
PipelineLayout* layout) const { PipelineLayout* layout) const {
ASSERT(!IsError()); ASSERT(!IsError());
#ifdef DAWN_ENABLE_WGSL
std::ostringstream errorStream;
errorStream << "Tint HLSL failure:" << std::endl;
// TODO: Remove redundant SPIRV step between WGSL and HLSL.
tint::Context context;
tint::reader::spirv::Parser parser(&context, GetSpirv());
if (!parser.Parse()) {
errorStream << "Parser: " << parser.error() << std::endl;
return DAWN_VALIDATION_ERROR(errorStream.str().c_str());
}
tint::ast::Module module = parser.module();
if (!module.IsValid()) {
errorStream << "Invalid module generated..." << std::endl;
return DAWN_VALIDATION_ERROR(errorStream.str().c_str());
}
tint::TypeDeterminer typeDeterminer(&context, &module);
if (!typeDeterminer.Determine()) {
errorStream << "Type Determination: " << typeDeterminer.error();
return DAWN_VALIDATION_ERROR(errorStream.str().c_str());
}
tint::Validator validator;
if (!validator.Validate(&module)) {
errorStream << "Validation: " << validator.error() << std::endl;
return DAWN_VALIDATION_ERROR(errorStream.str().c_str());
}
tint::transform::BoundArrayAccessorsTransform boundArrayTransformer(&context, &module);
if (!boundArrayTransformer.Run()) {
errorStream << "Bound Array Accessors Transform: " << boundArrayTransformer.error()
<< std::endl;
return DAWN_VALIDATION_ERROR(errorStream.str().c_str());
}
tint::writer::hlsl::Generator generator(std::move(module));
// TODO: Switch to GenerateEntryPoint once HLSL writer supports it.
if (!generator.Generate()) {
errorStream << "Generator: " << generator.error() << std::endl;
return DAWN_VALIDATION_ERROR(errorStream.str().c_str());
}
return generator.result();
#else
return DAWN_VALIDATION_ERROR("Using Tint to generate HLSL is not supported.");
#endif // DAWN_ENABLE_WGSL
}
ResultOrError<std::string> ShaderModule::TranslateToHLSLWithSPIRVCross(
const char* entryPointName,
SingleShaderStage stage,
PipelineLayout* layout) const {
ASSERT(!IsError());
// If these options are changed, the values in DawnSPIRVCrossHLSLFastFuzzer.cpp need to // If these options are changed, the values in DawnSPIRVCrossHLSLFastFuzzer.cpp need to
// be updated. // be updated.
spirv_cross::CompilerGLSL::Options options_glsl; spirv_cross::CompilerGLSL::Options options_glsl;

View File

@ -40,9 +40,13 @@ namespace dawn_native { namespace d3d12 {
static ResultOrError<ShaderModule*> Create(Device* device, static ResultOrError<ShaderModule*> Create(Device* device,
const ShaderModuleDescriptor* descriptor); const ShaderModuleDescriptor* descriptor);
ResultOrError<std::string> TranslateToHLSL(const char* entryPointName, ResultOrError<std::string> TranslateToHLSLWithTint(const char* entryPointName,
SingleShaderStage stage, SingleShaderStage stage,
PipelineLayout* layout) const; PipelineLayout* layout) const;
ResultOrError<std::string> TranslateToHLSLWithSPIRVCross(const char* entryPointName,
SingleShaderStage stage,
PipelineLayout* layout) const;
private: private:
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor); ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);

View File

@ -637,6 +637,15 @@ bool DawnTestBase::IsAsan() const {
#endif #endif
} }
bool DawnTestBase::HasToggleEnabled(const char* toggle) const {
for (const char* toggleEnabled : mParam.forceEnabledWorkarounds) {
if (strcmp(toggle, toggleEnabled) == 0) {
return true;
}
}
return false;
}
bool DawnTestBase::HasVendorIdFilter() const { bool DawnTestBase::HasVendorIdFilter() const {
return gTestEnv->HasVendorIdFilter(); return gTestEnv->HasVendorIdFilter();
} }

View File

@ -254,6 +254,8 @@ class DawnTestBase {
bool IsAsan() const; bool IsAsan() const;
bool HasToggleEnabled(const char* workaround) const;
void StartExpectDeviceError(); void StartExpectDeviceError();
bool EndExpectDeviceError(); bool EndExpectDeviceError();

View File

@ -72,6 +72,10 @@ TEST_P(EntryPointTests, TwoComputeInModule) {
// TODO: Reenable once Tint is able to produce Vulkan 1.0 / 1.1 SPIR-V. // TODO: Reenable once Tint is able to produce Vulkan 1.0 / 1.1 SPIR-V.
DAWN_SKIP_TEST_IF(IsVulkan()); DAWN_SKIP_TEST_IF(IsVulkan());
// TODO: Reenable once Tint's HLSL writer supports multiple entryPoints on a single stage.
// https://crbug.com/tint/297
DAWN_SKIP_TEST_IF(IsD3D12() && HasToggleEnabled("use_tint_generator"));
wgpu::ShaderModule module = utils::CreateShaderModuleFromWGSL(device, R"( wgpu::ShaderModule module = utils::CreateShaderModuleFromWGSL(device, R"(
[[block]] struct Data { [[block]] struct Data {
[[offset(0)]] data : u32; [[offset(0)]] data : u32;
@ -141,6 +145,7 @@ TEST_P(EntryPointTests, TwoComputeInModule) {
DAWN_INSTANTIATE_TEST(EntryPointTests, DAWN_INSTANTIATE_TEST(EntryPointTests,
D3D12Backend(), D3D12Backend(),
D3D12Backend({"use_tint_generator"}),
MetalBackend(), MetalBackend(),
OpenGLBackend(), OpenGLBackend(),
VulkanBackend()); VulkanBackend());