blob: 551d0d437450524c1d002bf1c2e6ee25a30358b2 [file]
/*
* Copyright (c) 2021-2024 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "CompilationMessage.h"
#include "CompilationScope.h"
#include "ConstantValue.h"
#include "WGSLEnums.h"
#include <cinttypes>
#include <cstdint>
#include <memory>
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/OptionSet.h>
#include <wtf/UniqueRef.h>
#include <wtf/Variant.h>
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
namespace WGSL {
//
// Step 1
//
class ShaderModule;
class CompilationScope;
namespace AST {
class Expression;
}
struct SuccessfulCheck {
SuccessfulCheck() = delete;
SuccessfulCheck(SuccessfulCheck&&);
SuccessfulCheck(Vector<Warning>&&, UniqueRef<ShaderModule>&&);
~SuccessfulCheck();
Vector<Warning> warnings;
UniqueRef<ShaderModule> ast;
};
struct FailedCheck {
Vector<Error> errors;
Vector<Warning> warnings;
};
struct SourceMap {
// I don't know what goes in here.
// https://sourcemaps.info/spec.html
};
struct Configuration {
uint32_t maxBuffersPlusVertexBuffersForVertexStage = 8;
uint32_t maxBuffersForFragmentStage = 8;
uint32_t maxBuffersForComputeStage = 8;
uint32_t maximumCombinedWorkgroupVariablesSize = 16384;
const HashSet<String> supportedFeatures = { };
};
Variant<SuccessfulCheck, FailedCheck> staticCheck(const String& wgsl, const std::optional<SourceMap>&, const Configuration&);
//
// Step 2
//
enum class BufferBindingType : uint8_t {
Uniform,
Storage,
ReadOnlyStorage
};
struct BufferBindingLayout {
BufferBindingType type;
bool hasDynamicOffset;
uint64_t minBindingSize;
};
enum class SamplerBindingType : uint8_t {
Filtering,
NonFiltering,
Comparison
};
struct SamplerBindingLayout {
SamplerBindingType type;
};
enum class TextureSampleType : uint8_t {
Float,
UnfilterableFloat,
Depth,
SignedInt,
UnsignedInt
};
enum class TextureViewDimension : uint8_t {
OneDimensional,
TwoDimensional,
TwoDimensionalArray,
Cube,
CubeArray,
ThreeDimensional
};
struct TextureBindingLayout {
TextureSampleType sampleType;
TextureViewDimension viewDimension;
bool multisampled;
};
enum class StorageTextureAccess : uint8_t {
WriteOnly,
ReadOnly,
ReadWrite,
};
struct StorageTextureBindingLayout {
StorageTextureAccess access { StorageTextureAccess::WriteOnly };
TexelFormat format;
TextureViewDimension viewDimension;
};
struct ExternalTextureBindingLayout {
// Sentinel
};
struct BindGroupLayoutEntry {
uint32_t binding;
uint32_t webBinding;
OptionSet<ShaderStage> visibility;
using BindingMember = Variant<BufferBindingLayout, SamplerBindingLayout, TextureBindingLayout, StorageTextureBindingLayout, ExternalTextureBindingLayout>;
BindingMember bindingMember;
String name;
std::optional<uint32_t> vertexArgumentBufferIndex;
std::optional<uint32_t> vertexArgumentBufferSizeIndex;
std::optional<uint32_t> vertexBufferDynamicOffset;
std::optional<uint32_t> fragmentArgumentBufferIndex;
std::optional<uint32_t> fragmentArgumentBufferSizeIndex;
std::optional<uint32_t> fragmentBufferDynamicOffset;
std::optional<uint32_t> computeArgumentBufferIndex;
std::optional<uint32_t> computeArgumentBufferSizeIndex;
std::optional<uint32_t> computeBufferDynamicOffset;
};
struct BindGroupLayout {
// Metal's [[id(n)]] indices are equal to the index into this vector.
uint32_t group;
Vector<BindGroupLayoutEntry> entries;
};
struct PipelineLayout {
// Metal's [[buffer(n)]] indices are equal to the index into this vector.
Vector<BindGroupLayout> bindGroupLayouts;
};
namespace Reflection {
struct Vertex {
bool invariantIsPresent;
// Tons of reflection data to appear here in the future.
};
struct Fragment {
// Tons of reflection data to appear here in the future.
};
struct WorkgroupSize {
const AST::Expression* width;
const AST::Expression* height;
const AST::Expression* depth;
};
struct Compute {
WorkgroupSize workgroupSize;
};
enum class SpecializationConstantType : uint8_t {
Boolean,
Float,
Int,
Unsigned,
Half
};
struct SpecializationConstant {
String mangledName;
SpecializationConstantType type;
AST::Expression* defaultValue;
};
struct EntryPointInformation {
String originalName;
String mangledName;
std::optional<PipelineLayout> defaultLayout; // If the input PipelineLayout is nullopt, the compiler computes a layout and returns it. https://gpuweb.github.io/gpuweb/#default-pipeline-layout
HashMap<String, SpecializationConstant> specializationConstants;
Variant<Vertex, Fragment, Compute> typedEntryPoint;
size_t sizeForWorkgroupVariables { 0 };
size_t bindingCount { 0 };
};
} // namespace Reflection
struct PrepareResult {
HashMap<String, Reflection::EntryPointInformation> entryPoints;
CompilationScope compilationScope;
};
struct DeviceState {
unsigned appleGPUFamily { 4 };
bool shaderValidationEnabled { false };
};
Variant<PrepareResult, Error> prepare(ShaderModule&, const HashMap<String, PipelineLayout*>&);
Variant<PrepareResult, Error> prepare(ShaderModule&, const String& entryPointName, PipelineLayout*);
Variant<String, Error> generate(ShaderModule&, PrepareResult&, HashMap<String, ConstantValue>&, DeviceState&&);
std::optional<ConstantValue> evaluate(const AST::Expression&, const HashMap<String, ConstantValue>&);
} // namespace WGSL