Commit 9bc837f6 by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: Generate SPIR-V directly from the translator; Part 1

This is the first change in a series to generate SPIR-V directly from the translator's AST, instead of the generating text GLSL and feeding it to glslang. This change implements the majority of the work needed to map AST types to SPIR-V types, and declare types and interface variables in SPIR-V. Additionally, it lays the infrastructure to conditionally enabling this path in end2end tests. No tests are currently enabled as the change doesn't actually generate code for function bodies yet. Bug: angleproject:4889 Change-Id: Iacb28b6907fd48c50e4cc5a0e7ad72f6eed241d4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2889603 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 3e453559
......@@ -543,6 +543,12 @@ template("translator_lib") {
# This translator is needed by metal backend also.
sources += angle_translator_lib_vulkan_sources
# Enable direct SPIR-V generation conditionally to avoid increasing binary size of ANGLE on
# official builds until that's the only path.
if (dcheck_always_on || is_debug) {
defines += [ "ANGLE_ENABLE_DIRECT_SPIRV_GENERATION" ]
}
}
if (angle_enable_vulkan || use_fuzzing_engine) {
......@@ -573,8 +579,10 @@ template("translator_lib") {
if (_uses_spirv) {
deps += [
"$angle_root/src/common/spirv:angle_spirv_base",
"$angle_root/src/common/spirv:angle_spirv_builder",
"${angle_glslang_dir}:glslang_default_resource_limits_sources",
"${angle_glslang_dir}:glslang_lib_sources",
"${angle_spirv_headers_dir}:spv_headers",
"${angle_spirv_tools_dir}:spvtools_headers",
"${angle_spirv_tools_dir}:spvtools_val",
]
......
......@@ -26,7 +26,7 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 257
#define ANGLE_SH_VERSION 258
enum ShShaderSpec
{
......@@ -337,6 +337,10 @@ const ShCompileOptions SH_ADD_VULKAN_XFB_EXTENSION_SUPPORT_CODE = UINT64_C(1) <<
// gl_FragColor is not written.
const ShCompileOptions SH_INIT_FRAGMENT_OUTPUT_VARIABLES = UINT64_C(1) << 57;
// Transitory flag to select between producing SPIR-V directly vs using glslang. Ignored in
// non-dcheck-enabled builds to avoid increasing ANGLE's binary size while both generators coexist.
const ShCompileOptions SH_GENERATE_SPIRV_DIRECTLY = UINT64_C(1) << 58;
// Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy
{
......
......@@ -83,6 +83,12 @@ struct FeaturesMtl : FeatureSetBase
Feature forceD24S8AsUnsupported = {"force_d24s8_as_unsupported", FeatureCategory::MetalFeatures,
"Force Depth24Stencil8 format as unsupported.", &members};
// Whether SPIR-V should be generated directly instead of through glslang. Transitory feature
// until the work is complete.
Feature directSPIRVGeneration = {"directSPIRVGeneration", FeatureCategory::MetalFeatures,
"Direct translation to SPIR-V.", &members,
"http://anglebug.com/4889"};
};
} // namespace angle
......
......@@ -489,6 +489,12 @@ struct FeaturesVk : FeatureSetBase
"Emulate 270-degree prerotation.", &members,
"http://anglebug.com/4901"};
// Whether SPIR-V should be generated directly instead of through glslang. Transitory feature
// until the work is complete.
Feature directSPIRVGeneration = {"directSPIRVGeneration", FeatureCategory::VulkanFeatures,
"Direct translation to SPIR-V.", &members,
"http://anglebug.com/4889"};
// Whether we should use driver uniforms over specialization constants for some shader
// modifications like yflip and rotation.
Feature forceDriverUniformOverSpecConst = {
......
......@@ -37,11 +37,11 @@ using Microsoft::WRL::ComPtr;
#endif // defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
#if defined(ANGLE_USE_ABSEIL)
template <typename Key, typename T>
using HashMap = absl::flat_hash_map<Key, T>;
template <typename Key, typename T, class Hash = absl::container_internal::hash_default_hash<Key>>
using HashMap = absl::flat_hash_map<Key, T, Hash>;
#else
template <typename Key, typename T>
using HashMap = std::unordered_map<Key, T>;
template <typename Key, typename T, class Hash = std::hash<Key>>
using HashMap = std::unordered_map<Key, T, Hash>;
#endif // defined(ANGLE_USE_ABSEIL)
class NonCopyable
......
......@@ -309,6 +309,10 @@ angle_translator_hlsl_sources = [
"src/compiler/translator/tree_ops/d3d/WrapSwitchStatementsInBlocks.h",
]
angle_translator_lib_vulkan_sources = [
"src/compiler/translator/BuildSPIRV.cpp",
"src/compiler/translator/BuildSPIRV.h",
"src/compiler/translator/OutputSPIRV.cpp",
"src/compiler/translator/OutputSPIRV.h",
"src/compiler/translator/OutputVulkanGLSL.cpp",
"src/compiler/translator/OutputVulkanGLSL.h",
"src/compiler/translator/TranslatorVulkan.cpp",
......
......@@ -1125,14 +1125,18 @@ enum TLayoutImageInternalFormat
EiifRGBA8I,
EiifR32I,
EiifRGBA8,
EiifRGBA8_SNORM
EiifRGBA8_SNORM,
EiifLast = EiifRGBA8_SNORM,
};
enum TLayoutMatrixPacking
{
EmpUnspecified,
EmpRowMajor,
EmpColumnMajor
EmpColumnMajor,
EmpLast = EmpColumnMajor,
};
enum TLayoutBlockStorage
......@@ -1141,7 +1145,9 @@ enum TLayoutBlockStorage
EbsShared,
EbsPacked,
EbsStd140,
EbsStd430
EbsStd430,
EbsLast = EbsStd430,
};
enum TYuvCscStandardEXT
......
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// OutputSPIRV: Generate SPIR-V from the AST.
//
#ifndef COMPILER_TRANSLATOR_OUTPUTSPIRV_H_
#define COMPILER_TRANSLATOR_OUTPUTSPIRV_H_
#include "compiler/translator/Compiler.h"
namespace sh
{
bool OutputSPIRV(TCompiler *compiler, TIntermBlock *root, ShCompileOptions compileOptions);
} // namespace sh
#endif // COMPILER_TRANSLATOR_OUTPUTSPIRV_H_
......@@ -73,16 +73,12 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
TIntermSymbol *symbol = variable->getAsSymbolNode();
ASSERT(symbol);
ImmutableString name = symbol->getName();
const char *blockStorage = nullptr;
const char *matrixPacking = nullptr;
// For interface blocks, use the block name instead. When the layout qualifier is being
// replaced in the backend, that would be the name that's available.
if (type.isInterfaceBlock())
{
const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
name = interfaceBlock->name();
TLayoutBlockStorage storage = interfaceBlock->blockStorage();
// Make sure block storage format is specified.
......@@ -128,8 +124,9 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
if (needsLocation)
{
const unsigned int locationCount = CalculateVaryingLocationCount(symbol, getShaderType());
uint32_t location = IsShaderIn(type.getQualifier())
const unsigned int locationCount =
CalculateVaryingLocationCount(symbol->getType(), getShaderType());
uint32_t location = IsShaderIn(type.getQualifier())
? nextUnusedInputLocation(locationCount)
: nextUnusedOutputLocation(locationCount);
......
......@@ -17,6 +17,7 @@
#include "compiler/translator/BuiltinsWorkaroundGLSL.h"
#include "compiler/translator/ImmutableStringBuilder.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/OutputSPIRV.h"
#include "compiler/translator/OutputVulkanGLSL.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/glslang_wrapper.h"
......@@ -648,7 +649,6 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler,
ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler,
ShCompileOptions compileOptions,
TInfoSinkBase &sink,
TIntermBlock *root,
TSymbolTable *symbolTable,
SpecConst *specConst,
......@@ -1039,7 +1039,7 @@ bool TranslatorVulkan::translateImpl(TInfoSinkBase &sink,
if ((compileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION) != 0)
{
if (!AddBresenhamEmulationFS(this, compileOptions, sink, root, &getSymbolTable(),
if (!AddBresenhamEmulationFS(this, compileOptions, root, &getSymbolTable(),
specConst, driverUniforms, usesFragCoord))
{
return false;
......@@ -1338,6 +1338,13 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
}
}
#if defined(ANGLE_ENABLE_DIRECT_SPIRV_GENERATION)
if ((compileOptions & SH_GENERATE_SPIRV_DIRECTLY) != 0 && getShaderType() == GL_VERTEX_SHADER)
{
return OutputSPIRV(this, root, compileOptions);
}
#endif
// Write translated shader.
TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(),
getNameMap(), &getSymbolTable(), getShaderType(),
......
......@@ -79,9 +79,8 @@ int GetInterfaceBlockLocationCount(const TType &varyingType, bool ignoreVaryingA
return totalLocation;
}
int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize)
int GetLocationCount(const TType &varyingType, bool ignoreVaryingArraySize)
{
const TType &varyingType = varying->getType();
ASSERT(!varyingType.isInterfaceBlock());
if (varyingType.getStruct() != nullptr)
......@@ -267,7 +266,7 @@ void ValidateShaderInterfaceAndAssignLocations(TDiagnostics *diagnostics,
}
else
{
const int elementCount = GetLocationCount(varying, ignoreVaryingArraySize);
const int elementCount = GetLocationCount(varying->getType(), ignoreVaryingArraySize);
MarkVaryingLocations(diagnostics, varying, nullptr, location, elementCount,
&locationMap);
}
......@@ -344,9 +343,8 @@ void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics)
} // anonymous namespace
unsigned int CalculateVaryingLocationCount(TIntermSymbol *varying, GLenum shaderType)
unsigned int CalculateVaryingLocationCount(const TType &varyingType, GLenum shaderType)
{
const TType &varyingType = varying->getType();
const TQualifier qualifier = varyingType.getQualifier();
const bool ignoreVaryingArraySize = ShouldIgnoreVaryingArraySize(qualifier, shaderType);
......@@ -355,7 +353,7 @@ unsigned int CalculateVaryingLocationCount(TIntermSymbol *varying, GLenum shader
return GetInterfaceBlockLocationCount(varyingType, ignoreVaryingArraySize);
}
return GetLocationCount(varying, ignoreVaryingArraySize);
return GetLocationCount(varyingType, ignoreVaryingArraySize);
}
bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType)
......
......@@ -18,8 +18,9 @@ namespace sh
class TIntermBlock;
class TIntermSymbol;
class TDiagnostics;
class TType;
unsigned int CalculateVaryingLocationCount(TIntermSymbol *varying, GLenum shaderType);
unsigned int CalculateVaryingLocationCount(const TType &varyingType, GLenum shaderType);
bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType);
} // namespace sh
......
......@@ -4907,6 +4907,8 @@ angle::Result GlslangTransformSpirvCode(const GlslangSpirvOptions &options,
aliasingTransformer.transform();
}
spirvBlobOut->shrink_to_fit();
ASSERT(spirv::Validate(*spirvBlobOut));
return angle::Result::Continue;
......
......@@ -12,6 +12,7 @@
#include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/metal/ContextMtl.h"
#include "libANGLE/renderer/metal/DisplayMtl.h"
namespace rx
{
......@@ -24,6 +25,8 @@ std::shared_ptr<WaitableCompileEvent> ShaderMtl::compile(const gl::Context *cont
gl::ShCompilerInstance *compilerInstance,
ShCompileOptions options)
{
ContextMtl *contextMtl = mtl::GetImpl(context);
ShCompileOptions compileOptions = SH_INITIALIZE_UNINITIALIZED_LOCALS;
bool isWebGL = context->getExtensions().webglCompatibility;
......@@ -37,6 +40,11 @@ std::shared_ptr<WaitableCompileEvent> ShaderMtl::compile(const gl::Context *cont
// Transform feedback is always emulated on Metal.
compileOptions |= SH_ADD_VULKAN_XFB_EMULATION_SUPPORT_CODE;
if (contextMtl->getDisplay()->getFeatures().directSPIRVGeneration.enabled)
{
compileOptions |= SH_GENERATE_SPIRV_DIRECTLY;
}
return compileImpl(context, compilerInstance, mState.getSource(), compileOptions | options);
}
......
......@@ -101,6 +101,11 @@ std::shared_ptr<WaitableCompileEvent> ShaderVk::compile(const gl::Context *conte
compileOptions |= SH_ADD_VULKAN_XFB_EMULATION_SUPPORT_CODE;
}
if (contextVk->getFeatures().directSPIRVGeneration.enabled)
{
compileOptions |= SH_GENERATE_SPIRV_DIRECTLY;
}
return compileImpl(context, compilerInstance, mState.getSource(), compileOptions | options);
}
......
......@@ -273,6 +273,11 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp)
stream << "_EmulatedVAOs";
}
if (pp.eglParameters.directSPIRVGeneration == EGL_TRUE)
{
stream << "_DirectSPIRVGen";
}
return stream;
}
......
......@@ -297,6 +297,12 @@ inline PlatformParameters WithEmulatedVAOs(const PlatformParameters &params)
return emualtedVAOParams;
}
inline PlatformParameters WithDirectSPIRVGeneration(const PlatformParameters &params)
{
PlatformParameters directSPIRVGeneration = params;
directSPIRVGeneration.eglParameters.directSPIRVGeneration = true;
return directSPIRVGeneration;
}
} // namespace angle
#endif // ANGLE_TEST_CONFIGS_H_
......@@ -64,7 +64,8 @@ struct EGLPlatformParameters
shaderStencilOutputFeature, genMultipleMipsPerPassFeature, platformMethods,
robustness, emulatedPrerotation, asyncCommandQueueFeatureVulkan,
hasExplicitMemBarrierFeatureMtl, hasCheapRenderPassFeatureMtl,
forceBufferGPUStorageFeatureMtl, supportsVulkanViewportFlip, emulatedVAOs);
forceBufferGPUStorageFeatureMtl, supportsVulkanViewportFlip, emulatedVAOs,
directSPIRVGeneration);
}
EGLint renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
......@@ -87,6 +88,7 @@ struct EGLPlatformParameters
EGLint forceBufferGPUStorageFeatureMtl = EGL_DONT_CARE;
EGLint supportsVulkanViewportFlip = EGL_DONT_CARE;
EGLint emulatedVAOs = EGL_DONT_CARE;
EGLint directSPIRVGeneration = EGL_DONT_CARE;
angle::PlatformMethods *platformMethods = nullptr;
};
......
......@@ -253,6 +253,11 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow,
enabledFeatureOverrides.push_back("asynchronousCommandProcessing");
}
if (params.directSPIRVGeneration == EGL_TRUE)
{
enabledFeatureOverrides.push_back("directSPIRVGeneration");
}
if (params.hasExplicitMemBarrierFeatureMtl == EGL_FALSE)
{
disabledFeatureOverrides.push_back("has_explicit_mem_barrier_mtl");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment