Title: [290267] trunk/Source/WebGPU
Revision
290267
Author
[email protected]
Date
2022-02-21 13:34:13 -0800 (Mon, 21 Feb 2022)

Log Message

[WebGPU] Tracer bullet part 11: Implement shader creation methods
https://bugs.webkit.org/show_bug.cgi?id=236933

Reviewed by Dean Jackson.

This implements Device::createShaderModule() and Device::createComputePipeline(). The async versions (neither
the WebGPU nor the Metal flavor) aren't implemented yet; this is just the first basic implementation.

* WebGPU/ComputePipeline.mm:
(WebGPU::createLibrary):
(WebGPU::createConstantValues):
(WebGPU::createFunction):
(WebGPU::createComputePipelineState):
(WebGPU::Device::createComputePipeline):
(WebGPU::Device::createComputePipelineAsync):
* WebGPU/PipelineLayout.h:
* WebGPU/PipelineLayout.mm:
(WebGPU::PipelineLayout::operator== const):
(WebGPU::PipelineLayout::operator!= const):
* WebGPU/ShaderModule.h:
(WebGPU::ShaderModule::create):
* WebGPU/ShaderModule.mm:
(WebGPU::findShaderModuleParameters):
(WebGPU::ShaderModule::createLibrary):
(WebGPU::earlyCompileShaderModule):
(WebGPU::Device::createShaderModule):
(WebGPU::ShaderModule::ShaderModule):
(WebGPU::CompilationMessageData::CompilationMessageData):
(WebGPU::convertMessages):
(WebGPU::ShaderModule::getCompilationInfo):
(WebGPU::ShaderModule::setLabel):
(WebGPU::ShaderModule::convertPipelineLayout):
(WebGPU::ShaderModule::ast const):
(WebGPU::ShaderModule::pipelineLayoutHint const):
(WebGPU::ShaderModule::entryPointInformation const):

Modified Paths

Diff

Modified: trunk/Source/WebGPU/ChangeLog (290266 => 290267)


--- trunk/Source/WebGPU/ChangeLog	2022-02-21 21:32:31 UTC (rev 290266)
+++ trunk/Source/WebGPU/ChangeLog	2022-02-21 21:34:13 UTC (rev 290267)
@@ -1,5 +1,43 @@
 2022-02-21  Myles C. Maxfield  <[email protected]>
 
+        [WebGPU] Tracer bullet part 11: Implement shader creation methods
+        https://bugs.webkit.org/show_bug.cgi?id=236933
+
+        Reviewed by Dean Jackson.
+
+        This implements Device::createShaderModule() and Device::createComputePipeline(). The async versions (neither
+        the WebGPU nor the Metal flavor) aren't implemented yet; this is just the first basic implementation.
+
+        * WebGPU/ComputePipeline.mm:
+        (WebGPU::createLibrary):
+        (WebGPU::createConstantValues):
+        (WebGPU::createFunction):
+        (WebGPU::createComputePipelineState):
+        (WebGPU::Device::createComputePipeline):
+        (WebGPU::Device::createComputePipelineAsync):
+        * WebGPU/PipelineLayout.h:
+        * WebGPU/PipelineLayout.mm:
+        (WebGPU::PipelineLayout::operator== const):
+        (WebGPU::PipelineLayout::operator!= const):
+        * WebGPU/ShaderModule.h:
+        (WebGPU::ShaderModule::create):
+        * WebGPU/ShaderModule.mm:
+        (WebGPU::findShaderModuleParameters):
+        (WebGPU::ShaderModule::createLibrary):
+        (WebGPU::earlyCompileShaderModule):
+        (WebGPU::Device::createShaderModule):
+        (WebGPU::ShaderModule::ShaderModule):
+        (WebGPU::CompilationMessageData::CompilationMessageData):
+        (WebGPU::convertMessages):
+        (WebGPU::ShaderModule::getCompilationInfo):
+        (WebGPU::ShaderModule::setLabel):
+        (WebGPU::ShaderModule::convertPipelineLayout):
+        (WebGPU::ShaderModule::ast const):
+        (WebGPU::ShaderModule::pipelineLayoutHint const):
+        (WebGPU::ShaderModule::entryPointInformation const):
+
+2022-02-21  Myles C. Maxfield  <[email protected]>
+
         [WebGPU] Tracer bullet part 10: Implement setLabel() and Metal accessors
         https://bugs.webkit.org/show_bug.cgi?id=236910
 

Modified: trunk/Source/WebGPU/WebGPU/ComputePipeline.mm (290266 => 290267)


--- trunk/Source/WebGPU/WebGPU/ComputePipeline.mm	2022-02-21 21:32:31 UTC (rev 290266)
+++ trunk/Source/WebGPU/WebGPU/ComputePipeline.mm	2022-02-21 21:34:13 UTC (rev 290267)
@@ -29,17 +29,150 @@
 
 #import "BindGroupLayout.h"
 #import "Device.h"
+#import "PipelineLayout.h"
+#import "ShaderModule.h"
 
 namespace WebGPU {
 
+struct LibraryCreationResult {
+    id <MTLLibrary> library;
+    WGSL::Reflection::EntryPointInformation entryPointInformation; // FIXME: This is big. Don't copy this around.
+};
+
+static std::optional<LibraryCreationResult> createLibrary(id <MTLDevice> device, const ShaderModule& shaderModule, const PipelineLayout& pipelineLayout, const String& entryPoint, NSString *label)
+{
+    if (shaderModule.library()) {
+        if (const auto* pipelineLayoutHint = shaderModule.pipelineLayoutHint(entryPoint)) {
+            if (*pipelineLayoutHint == pipelineLayout) {
+                if (const auto* entryPointInformation = shaderModule.entryPointInformation(entryPoint))
+                    return { { shaderModule.library(), *entryPointInformation } };
+            }
+        }
+    }
+
+    const auto* ast = shaderModule.ast();
+    if (!ast)
+        return std::nullopt;
+
+    auto prepareResult = WGSL::prepare(*ast, entryPoint, ShaderModule::convertPipelineLayout(pipelineLayout));
+
+    auto library = ShaderModule::createLibrary(device, prepareResult.msl, label);
+
+    auto iterator = prepareResult.entryPoints.find(entryPoint);
+    if (iterator == prepareResult.entryPoints.end())
+        return std::nullopt;
+    const auto& entryPointInformation = iterator->value;
+
+    return { { library, entryPointInformation } };
+}
+
+static MTLFunctionConstantValues *createConstantValues(uint32_t constantCount, const WGPUConstantEntry* constants, const WGSL::Reflection::EntryPointInformation& entryPointInformation)
+{
+    auto constantValues = [MTLFunctionConstantValues new];
+    for (uint32_t i = 0; i < constantCount; ++i) {
+        const auto& entry = constants[i];
+        auto nameIterator = entryPointInformation.specializationConstantIndices.find(entry.key);
+        if (nameIterator == entryPointInformation.specializationConstantIndices.end())
+            return nullptr;
+        auto specializationConstantIndex = nameIterator->value;
+        auto indexIterator = entryPointInformation.specializationConstants.find(specializationConstantIndex);
+        if (indexIterator == entryPointInformation.specializationConstants.end())
+            return nullptr;
+        const auto& specializationConstant = indexIterator->value;
+        switch (specializationConstant.type) {
+        case WGSL::Reflection::SpecializationConstantType::Boolean: {
+            bool value = entry.value;
+            [constantValues setConstantValue:&value type:MTLDataTypeBool withName:specializationConstant.mangledName];
+            break;
+        }
+        case WGSL::Reflection::SpecializationConstantType::Float: {
+            float value = entry.value;
+            [constantValues setConstantValue:&value type:MTLDataTypeFloat withName:specializationConstant.mangledName];
+            break;
+        }
+        case WGSL::Reflection::SpecializationConstantType::Int: {
+            int value = entry.value;
+            [constantValues setConstantValue:&value type:MTLDataTypeInt withName:specializationConstant.mangledName];
+            break;
+        }
+        case WGSL::Reflection::SpecializationConstantType::Unsigned: {
+            unsigned value = entry.value;
+            [constantValues setConstantValue:&value type:MTLDataTypeUInt withName:specializationConstant.mangledName];
+            break;
+        }
+        default:
+            return nullptr;
+        }
+    }
+    return constantValues;
+}
+
+static id <MTLFunction> createFunction(id <MTLLibrary> library, const WGSL::Reflection::EntryPointInformation& entryPointInformation, const WGPUProgrammableStageDescriptor& compute, NSString *label)
+{
+    auto functionDescriptor = [MTLFunctionDescriptor new];
+    functionDescriptor.name = entryPointInformation.mangledName;
+    if (compute.constantCount) {
+        auto constantValues = createConstantValues(compute.constantCount, compute.constants, entryPointInformation);
+        if (!constantValues)
+            return nullptr;
+        functionDescriptor.constantValues = constantValues;
+    }
+    NSError *error = nil;
+    id <MTLFunction> function = [library newFunctionWithDescriptor:functionDescriptor error:&error];
+    if (error)
+        WTFLogAlways("Function creation error: %@", error);
+    function.label = label;
+    return function;
+}
+
+static id <MTLComputePipelineState> createComputePipelineState(id <MTLDevice> device, id <MTLFunction> function, const PipelineLayout& pipelineLayout, const WGSL::Reflection::Compute& computeInformation, NSString *label)
+{
+    auto computePipelineDescriptor = [MTLComputePipelineDescriptor new];
+    computePipelineDescriptor.computeFunction = function;
+    // FIXME: check this calculation for overflow
+    computePipelineDescriptor.maxTotalThreadsPerThreadgroup = computeInformation.workgroupSize.width * computeInformation.workgroupSize.height * computeInformation.workgroupSize.depth;
+    for (size_t i = 0; i < pipelineLayout.numberOfBindGroupLayouts(); ++i)
+        computePipelineDescriptor.buffers[i].mutability = MTLMutabilityImmutable; // Argument buffers are always immutable in WebGPU.
+    computePipelineDescriptor.supportIndirectCommandBuffers = YES;
+    computePipelineDescriptor.label = label;
+    NSError *error = nil;
+    // FIXME: Run the asynchronous version of this
+    id <MTLComputePipelineState> computePipelineState = [device newComputePipelineStateWithDescriptor:computePipelineDescriptor options:MTLPipelineOptionNone reflection:nil error:&error];
+    if (error)
+        WTFLogAlways("Pipeline state creation error: %@", error);
+    return computePipelineState;
+}
+
 RefPtr<ComputePipeline> Device::createComputePipeline(const WGPUComputePipelineDescriptor* descriptor)
 {
-    UNUSED_PARAM(descriptor);
-    return ComputePipeline::create(nil);
+    if (descriptor->nextInChain || descriptor->compute.nextInChain)
+        return nullptr;
+
+    const ShaderModule& shaderModule = descriptor->compute.module->shaderModule;
+    const PipelineLayout& pipelineLayout = descriptor->layout->pipelineLayout;
+    auto label = [NSString stringWithCString:descriptor->label encoding:NSUTF8StringEncoding];
+
+    auto libraryCreationResult = createLibrary(m_device, shaderModule, pipelineLayout, descriptor->compute.entryPoint, label);
+    if (!libraryCreationResult)
+        return nullptr;
+
+    auto library = libraryCreationResult->library;
+    const auto& entryPointInformation = libraryCreationResult->entryPointInformation;
+
+    if (!std::holds_alternative<WGSL::Reflection::Compute>(entryPointInformation.typedEntryPoint))
+        return nullptr;
+    const auto& computeInformation = std::get<WGSL::Reflection::Compute>(entryPointInformation.typedEntryPoint);
+
+    auto function = createFunction(library, entryPointInformation, descriptor->compute, label);
+
+    auto computePipelineState = createComputePipelineState(m_device, function, pipelineLayout, computeInformation, label);
+
+    return ComputePipeline::create(computePipelineState);
 }
 
 void Device::createComputePipelineAsync(const WGPUComputePipelineDescriptor* descriptor, WTF::Function<void(WGPUCreatePipelineAsyncStatus, RefPtr<ComputePipeline>&&, const char* message)>&& callback)
 {
+    // FIXME: Implement this
     UNUSED_PARAM(descriptor);
     UNUSED_PARAM(callback);
 }

Modified: trunk/Source/WebGPU/WebGPU/PipelineLayout.h (290266 => 290267)


--- trunk/Source/WebGPU/WebGPU/PipelineLayout.h	2022-02-21 21:32:31 UTC (rev 290266)
+++ trunk/Source/WebGPU/WebGPU/PipelineLayout.h	2022-02-21 21:34:13 UTC (rev 290267)
@@ -46,6 +46,9 @@
 
     void setLabel(const char*);
 
+    bool operator==(const PipelineLayout&) const;
+    bool operator!=(const PipelineLayout&) const;
+
     size_t numberOfBindGroupLayouts() const { return m_bindGroupLayouts.size(); }
     const BindGroupLayout& bindGroupLayout(size_t i) const { return m_bindGroupLayouts[i]; }
 

Modified: trunk/Source/WebGPU/WebGPU/PipelineLayout.mm (290266 => 290267)


--- trunk/Source/WebGPU/WebGPU/PipelineLayout.mm	2022-02-21 21:32:31 UTC (rev 290266)
+++ trunk/Source/WebGPU/WebGPU/PipelineLayout.mm	2022-02-21 21:34:13 UTC (rev 290267)
@@ -57,8 +57,20 @@
     // There is no Metal object that represents a pipeline layout.
 }
 
+bool PipelineLayout::operator==(const PipelineLayout& other) const
+{
+    UNUSED_PARAM(other);
+    // FIXME: Implement this
+    return false;
 }
 
+bool PipelineLayout::operator!=(const PipelineLayout& other) const
+{
+    return !(*this == other);
+}
+
+}
+
 void wgpuPipelineLayoutRelease(WGPUPipelineLayout pipelineLayout)
 {
     delete pipelineLayout;

Modified: trunk/Source/WebGPU/WebGPU/ShaderModule.h (290266 => 290267)


--- trunk/Source/WebGPU/WebGPU/ShaderModule.h	2022-02-21 21:32:31 UTC (rev 290266)
+++ trunk/Source/WebGPU/WebGPU/ShaderModule.h	2022-02-21 21:34:13 UTC (rev 290267)
@@ -25,18 +25,23 @@
 
 #pragma once
 
+#import "WGSL.h"
 #import <wtf/FastMalloc.h>
 #import <wtf/Ref.h>
 #import <wtf/RefCounted.h>
+#import <wtf/text/StringHash.h>
+#import <wtf/text/WTFString.h>
 
 namespace WebGPU {
 
+class PipelineLayout;
+
 class ShaderModule : public RefCounted<ShaderModule> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    static Ref<ShaderModule> create(id <MTLLibrary> library)
+    static Ref<ShaderModule> create(std::variant<WGSL::SuccessfulCheck, WGSL::FailedCheck>&& checkResult, HashMap<String, Ref<PipelineLayout>>&& pipelineLayoutHints, HashMap<String, WGSL::Reflection::EntryPointInformation>&& entryPointInformation, id <MTLLibrary> library)
     {
-        return adoptRef(*new ShaderModule(library));
+        return adoptRef(*new ShaderModule(WTFMove(checkResult), WTFMove(pipelineLayoutHints), WTFMove(entryPointInformation), library));
     }
 
     ~ShaderModule();
@@ -44,12 +49,22 @@
     void getCompilationInfo(WTF::Function<void(WGPUCompilationInfoRequestStatus, const WGPUCompilationInfo*)>&& callback);
     void setLabel(const char*);
 
+    static WGSL::PipelineLayout convertPipelineLayout(const PipelineLayout&);
+    static id <MTLLibrary> createLibrary(id <MTLDevice>, const String& msl, NSString *label);
+
+    const WGSL::AST* ast() const;
+
+    const PipelineLayout* pipelineLayoutHint(const String&) const;
+    const WGSL::Reflection::EntryPointInformation* entryPointInformation(const String&) const;
     id <MTLLibrary> library() const { return m_library; }
 
 private:
-    ShaderModule(id <MTLLibrary>);
+    ShaderModule(std::variant<WGSL::SuccessfulCheck, WGSL::FailedCheck>&&, HashMap<String, Ref<PipelineLayout>>&&, HashMap<String, WGSL::Reflection::EntryPointInformation>&&, id <MTLLibrary>);
 
-    id <MTLLibrary> m_library { nil };
+    const std::variant<WGSL::SuccessfulCheck, WGSL::FailedCheck> m_checkResult;
+    const HashMap<String, Ref<PipelineLayout>> m_pipelineLayoutHints;
+    const HashMap<String, WGSL::Reflection::EntryPointInformation> m_entryPointInformation;
+    id <MTLLibrary> m_library { nil }; // This is only non-null if we could compile the module early.
 };
 
 } // namespace WebGPU

Modified: trunk/Source/WebGPU/WebGPU/ShaderModule.mm (290266 => 290267)


--- trunk/Source/WebGPU/WebGPU/ShaderModule.mm	2022-02-21 21:32:31 UTC (rev 290266)
+++ trunk/Source/WebGPU/WebGPU/ShaderModule.mm	2022-02-21 21:34:13 UTC (rev 290267)
@@ -27,32 +27,222 @@
 #import "ShaderModule.h"
 
 #import "Device.h"
+#import "PipelineLayout.h"
 
 namespace WebGPU {
 
+struct ShaderModuleParameters {
+    const WGPUShaderModuleWGSLDescriptor& wgsl;
+    const WGPUShaderModuleDescriptorHints* hints;
+};
+
+static std::optional<ShaderModuleParameters> findShaderModuleParameters(const WGPUShaderModuleDescriptor* descriptor)
+{
+    const WGPUShaderModuleWGSLDescriptor* wgsl = nullptr;
+    const WGPUShaderModuleDescriptorHints* hints = nullptr;
+
+    for (const WGPUChainedStruct* ptr = descriptor->nextInChain; ptr; ptr = ptr->next) {
+        auto type = ptr->sType;
+
+        switch (static_cast<int>(type)) {
+        case WGPUSType_ShaderModuleWGSLDescriptor:
+            if (wgsl)
+                return std::nullopt;
+            wgsl = reinterpret_cast<const WGPUShaderModuleWGSLDescriptor*>(ptr);
+            break;
+        case WGPUSTypeExtended_ShaderModuleDescriptorHints:
+            if (hints)
+                return std::nullopt;
+            hints = reinterpret_cast<const WGPUShaderModuleDescriptorHints*>(ptr);
+            break;
+        default:
+            return std::nullopt;
+        }
+    }
+
+    if (!wgsl)
+        return std::nullopt;
+
+    return { { *wgsl, hints } };
+}
+
+id <MTLLibrary> ShaderModule::createLibrary(id <MTLDevice> device, const String& msl, NSString *label)
+{
+    auto options = [MTLCompileOptions new];
+    options.fastMathEnabled = YES;
+    NSError *error = nil;
+    // FIXME: Run the asynchronous version of this
+    id <MTLLibrary> library = [device newLibraryWithSource:msl options:options error:&error];
+    if (error)
+        WTFLogAlways("MSL compilation error: %@", error);
+    library.label = label;
+    return library;
+}
+
+static RefPtr<ShaderModule> earlyCompileShaderModule(id <MTLDevice> device, std::variant<WGSL::SuccessfulCheck, WGSL::FailedCheck>&& checkResult, const WGPUShaderModuleDescriptorHints& suppliedHints, NSString *label)
+{
+    HashMap<String, Ref<PipelineLayout>> hints;
+    HashMap<String, WGSL::PipelineLayout> wgslHints;
+    for (uint32_t i = 0; i < suppliedHints.hintsCount; ++i) {
+        const auto& hint = suppliedHints.hints[i];
+        if (hint.nextInChain)
+            return nullptr;
+        hints.add(hint.key, hint.hint.layout->pipelineLayout);
+        auto convertedPipelineLayout = ShaderModule::convertPipelineLayout(hint.hint.layout->pipelineLayout);
+        wgslHints.add(hint.key, WTFMove(convertedPipelineLayout));
+    }
+    auto prepareResult = WGSL::prepare(std::get<WGSL::SuccessfulCheck>(checkResult).ast, wgslHints);
+    auto library = ShaderModule::createLibrary(device, prepareResult.msl, label);
+    if (!library)
+        return nullptr;
+    return ShaderModule::create(WTFMove(checkResult), WTFMove(hints), WTFMove(prepareResult.entryPoints), library);
+}
+
 RefPtr<ShaderModule> Device::createShaderModule(const WGPUShaderModuleDescriptor* descriptor)
 {
-    UNUSED_PARAM(descriptor);
-    return ShaderModule::create(nil);
+    if (!descriptor->nextInChain)
+        return nullptr;
+
+    auto shaderModuleParameters = findShaderModuleParameters(descriptor);
+    if (!shaderModuleParameters)
+        return nullptr;
+
+    auto checkResult = WGSL::staticCheck(String(shaderModuleParameters->wgsl.code), std::nullopt);
+
+    if (std::holds_alternative<WGSL::SuccessfulCheck>(checkResult) && shaderModuleParameters->hints && shaderModuleParameters->hints->hintsCount) {
+        if (auto result = earlyCompileShaderModule(m_device, WTFMove(checkResult), *shaderModuleParameters->hints, [NSString stringWithCString:descriptor->label encoding:NSUTF8StringEncoding]))
+            return result;
+    }
+
+    return ShaderModule::create(WTFMove(checkResult), { }, { }, nil);
 }
 
-ShaderModule::ShaderModule(id <MTLLibrary> library)
-    : m_library(library)
+ShaderModule::ShaderModule(std::variant<WGSL::SuccessfulCheck, WGSL::FailedCheck>&& checkResult, HashMap<String, Ref<PipelineLayout>>&& pipelineLayoutHints, HashMap<String, WGSL::Reflection::EntryPointInformation>&& entryPointInformation, id <MTLLibrary> library)
+    : m_checkResult(WTFMove(checkResult))
+    , m_pipelineLayoutHints(WTFMove(pipelineLayoutHints))
+    , m_entryPointInformation(WTFMove(entryPointInformation))
+    , m_library(library)
 {
 }
 
 ShaderModule::~ShaderModule() = default;
 
+struct Messages {
+    const Vector<WGSL::CompilationMessage>& messages;
+    WGPUCompilationMessageType type;
+};
+
+struct CompilationMessageData {
+    CompilationMessageData(Vector<WGPUCompilationMessage>&& compilationMessages, Vector<CString>&& messages)
+        : compilationMessages(WTFMove(compilationMessages))
+        , messages(WTFMove(messages))
+    {
+    }
+
+    CompilationMessageData(const CompilationMessageData&) = delete;
+    CompilationMessageData(CompilationMessageData&&) = default;
+
+    Vector<WGPUCompilationMessage> compilationMessages;
+    Vector<CString> messages;
+};
+
+static CompilationMessageData convertMessages(const Messages& messages1, const std::optional<Messages>& messages2 = std::nullopt)
+{
+    Vector<WGPUCompilationMessage> flattenedCompilationMessages;
+    Vector<CString> flattenedMessages;
+
+    auto populateMessages = [&] (const Messages& compilationMessages) {
+        for (const auto& compilationMessage : compilationMessages.messages)
+            flattenedMessages.append(compilationMessage.message.utf8());
+    };
+
+    populateMessages(messages1);
+    if (messages2)
+        populateMessages(*messages2);
+
+    auto populateCompilationMessages = [&] (const Messages& compilationMessages, size_t base) {
+        for (size_t i = 0; i < compilationMessages.messages.size(); ++i) {
+            const auto& compilationMessage = compilationMessages.messages[i];
+            flattenedCompilationMessages.append({
+                nullptr,
+                flattenedMessages[i + base].data(),
+                compilationMessages.type,
+                compilationMessage.lineNumber,
+                compilationMessage.linePosition,
+                compilationMessage.offset,
+                compilationMessage.length,
+            });
+        }
+    };
+
+    populateCompilationMessages(messages1, 0);
+    if (messages2)
+        populateCompilationMessages(*messages2, messages1.messages.size());
+
+    return { WTFMove(flattenedCompilationMessages), WTFMove(flattenedMessages) };
+}
+
 void ShaderModule::getCompilationInfo(WTF::Function<void(WGPUCompilationInfoRequestStatus, const WGPUCompilationInfo*)>&& callback)
 {
-    UNUSED_PARAM(callback);
+    WTF::switchOn(m_checkResult, [&] (const WGSL::SuccessfulCheck& successfulCheck) {
+        auto compilationMessageData(convertMessages({ successfulCheck.warnings, WGPUCompilationMessageType_Warning }));
+        WGPUCompilationInfo compilationInfo {
+            nullptr,
+            static_cast<uint32_t>(compilationMessageData.compilationMessages.size()),
+            compilationMessageData.compilationMessages.data(),
+        };
+        callback(WGPUCompilationInfoRequestStatus_Success, &compilationInfo);
+    }, [&] (const WGSL::FailedCheck& failedCheck) {
+        auto compilationMessageData(convertMessages(
+            { failedCheck.errors, WGPUCompilationMessageType_Error },
+            { { failedCheck.warnings, WGPUCompilationMessageType_Warning } }));
+        WGPUCompilationInfo compilationInfo {
+            nullptr,
+            static_cast<uint32_t>(compilationMessageData.compilationMessages.size()),
+            compilationMessageData.compilationMessages.data(),
+        };
+        callback(WGPUCompilationInfoRequestStatus_Error, &compilationInfo);
+    });
 }
 
 void ShaderModule::setLabel(const char* label)
 {
-    m_library.label = [NSString stringWithCString:label encoding:NSUTF8StringEncoding];
+    if (m_library)
+        m_library.label = [NSString stringWithCString:label encoding:NSUTF8StringEncoding];
 }
 
+WGSL::PipelineLayout ShaderModule::convertPipelineLayout(const PipelineLayout& pipelineLayout)
+{
+    UNUSED_PARAM(pipelineLayout);
+    // FIXME: Implement this
+    return { { } };
+}
+
+const WGSL::AST* ShaderModule::ast() const
+{
+    return WTF::switchOn(m_checkResult, [&] (const WGSL::SuccessfulCheck& successfulCheck) -> const WGSL::AST* {
+        return successfulCheck.ast.ptr();
+    }, [&] (const WGSL::FailedCheck&) -> const WGSL::AST* {
+        return nullptr;
+    });
+}
+
+const PipelineLayout* ShaderModule::pipelineLayoutHint(const String& name) const
+{
+    auto iterator = m_pipelineLayoutHints.find(name);
+    if (iterator == m_pipelineLayoutHints.end())
+        return nullptr;
+    return iterator->value.ptr();
+}
+
+const WGSL::Reflection::EntryPointInformation* ShaderModule::entryPointInformation(const String& name) const
+{
+    auto iterator = m_entryPointInformation.find(name);
+    if (iterator == m_entryPointInformation.end())
+        return nullptr;
+    return &iterator->value;
+}
+
 } // namespace WebGPU
 
 void wgpuShaderModuleRelease(WGPUShaderModule shaderModule)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to