Cache WGSL -> MSL compilation
Bug: dawn:1480 Change-Id: Ie2ef7860b38d7f350c99cf2c5451299b23413ec6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97882 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Loko Kung <lokokung@google.com>
This commit is contained in:
parent
e40bd8e964
commit
0671fe28bf
|
@ -333,6 +333,7 @@ source_set("sources") {
|
||||||
"UsageValidationMode.h",
|
"UsageValidationMode.h",
|
||||||
"VertexFormat.cpp",
|
"VertexFormat.cpp",
|
||||||
"VertexFormat.h",
|
"VertexFormat.h",
|
||||||
|
"VisitableMembers.h",
|
||||||
"dawn_platform.h",
|
"dawn_platform.h",
|
||||||
"stream/BlobSource.cpp",
|
"stream/BlobSource.cpp",
|
||||||
"stream/BlobSource.h",
|
"stream/BlobSource.h",
|
||||||
|
|
|
@ -190,6 +190,7 @@ target_sources(dawn_native PRIVATE
|
||||||
"UsageValidationMode.h"
|
"UsageValidationMode.h"
|
||||||
"VertexFormat.cpp"
|
"VertexFormat.cpp"
|
||||||
"VertexFormat.h"
|
"VertexFormat.h"
|
||||||
|
"VisitableMembers.h"
|
||||||
"dawn_platform.h"
|
"dawn_platform.h"
|
||||||
"webgpu_absl_format.cpp"
|
"webgpu_absl_format.cpp"
|
||||||
"webgpu_absl_format.h"
|
"webgpu_absl_format.h"
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "dawn/native/CacheResult.h"
|
#include "dawn/native/CacheResult.h"
|
||||||
#include "dawn/native/Device.h"
|
#include "dawn/native/Device.h"
|
||||||
#include "dawn/native/Error.h"
|
#include "dawn/native/Error.h"
|
||||||
|
#include "dawn/native/VisitableMembers.h"
|
||||||
|
|
||||||
namespace dawn::native {
|
namespace dawn::native {
|
||||||
|
|
||||||
|
@ -94,6 +95,15 @@ class CacheRequestImpl {
|
||||||
CacheRequestImpl(const CacheRequestImpl&) = delete;
|
CacheRequestImpl(const CacheRequestImpl&) = delete;
|
||||||
CacheRequestImpl& operator=(const CacheRequestImpl&) = delete;
|
CacheRequestImpl& operator=(const CacheRequestImpl&) = delete;
|
||||||
|
|
||||||
|
// Create a CacheKey from the request type and all members
|
||||||
|
CacheKey CreateCacheKey(const DeviceBase* device) const {
|
||||||
|
CacheKey key = device->GetCacheKey();
|
||||||
|
StreamIn(&key, Request::kName);
|
||||||
|
static_cast<const Request*>(this)->VisitAll(
|
||||||
|
[&](const auto&... members) { StreamIn(&key, members...); });
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename CacheHitFn, typename CacheMissFn>
|
template <typename CacheHitFn, typename CacheMissFn>
|
||||||
friend auto LoadOrRun(DeviceBase* device,
|
friend auto LoadOrRun(DeviceBase* device,
|
||||||
Request&& r,
|
Request&& r,
|
||||||
|
@ -168,19 +178,12 @@ class CacheRequestImpl {
|
||||||
// X(Bar, bar)
|
// X(Bar, bar)
|
||||||
// DAWN_MAKE_CACHE_REQUEST(MyCacheRequest, REQUEST_MEMBERS)
|
// DAWN_MAKE_CACHE_REQUEST(MyCacheRequest, REQUEST_MEMBERS)
|
||||||
// #undef REQUEST_MEMBERS
|
// #undef REQUEST_MEMBERS
|
||||||
#define DAWN_MAKE_CACHE_REQUEST(Request, MEMBERS) \
|
#define DAWN_MAKE_CACHE_REQUEST(Request, MEMBERS) \
|
||||||
class Request : public ::dawn::native::CacheRequestImpl<Request> { \
|
class Request : public ::dawn::native::CacheRequestImpl<Request> { \
|
||||||
public: \
|
public: \
|
||||||
Request() = default; \
|
static constexpr char kName[] = #Request; \
|
||||||
MEMBERS(DAWN_INTERNAL_CACHE_REQUEST_DECL_STRUCT_MEMBER) \
|
Request() = default; \
|
||||||
\
|
DAWN_VISITABLE_MEMBERS(MEMBERS) \
|
||||||
/* Create a CacheKey from the request type and all members */ \
|
|
||||||
::dawn::native::CacheKey CreateCacheKey(const ::dawn::native::DeviceBase* device) const { \
|
|
||||||
::dawn::native::CacheKey key = device->GetCacheKey(); \
|
|
||||||
StreamIn(&key, #Request); \
|
|
||||||
MEMBERS(DAWN_INTERNAL_CACHE_REQUEST_RECORD_KEY) \
|
|
||||||
return key; \
|
|
||||||
} \
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper macro for the common pattern of DAWN_TRY_ASSIGN around LoadOrRun.
|
// Helper macro for the common pattern of DAWN_TRY_ASSIGN around LoadOrRun.
|
||||||
|
|
|
@ -37,87 +37,6 @@ namespace dawn::native {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
tint::transform::VertexFormat ToTintVertexFormat(wgpu::VertexFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
case wgpu::VertexFormat::Uint8x2:
|
|
||||||
return tint::transform::VertexFormat::kUint8x2;
|
|
||||||
case wgpu::VertexFormat::Uint8x4:
|
|
||||||
return tint::transform::VertexFormat::kUint8x4;
|
|
||||||
case wgpu::VertexFormat::Sint8x2:
|
|
||||||
return tint::transform::VertexFormat::kSint8x2;
|
|
||||||
case wgpu::VertexFormat::Sint8x4:
|
|
||||||
return tint::transform::VertexFormat::kSint8x4;
|
|
||||||
case wgpu::VertexFormat::Unorm8x2:
|
|
||||||
return tint::transform::VertexFormat::kUnorm8x2;
|
|
||||||
case wgpu::VertexFormat::Unorm8x4:
|
|
||||||
return tint::transform::VertexFormat::kUnorm8x4;
|
|
||||||
case wgpu::VertexFormat::Snorm8x2:
|
|
||||||
return tint::transform::VertexFormat::kSnorm8x2;
|
|
||||||
case wgpu::VertexFormat::Snorm8x4:
|
|
||||||
return tint::transform::VertexFormat::kSnorm8x4;
|
|
||||||
case wgpu::VertexFormat::Uint16x2:
|
|
||||||
return tint::transform::VertexFormat::kUint16x2;
|
|
||||||
case wgpu::VertexFormat::Uint16x4:
|
|
||||||
return tint::transform::VertexFormat::kUint16x4;
|
|
||||||
case wgpu::VertexFormat::Sint16x2:
|
|
||||||
return tint::transform::VertexFormat::kSint16x2;
|
|
||||||
case wgpu::VertexFormat::Sint16x4:
|
|
||||||
return tint::transform::VertexFormat::kSint16x4;
|
|
||||||
case wgpu::VertexFormat::Unorm16x2:
|
|
||||||
return tint::transform::VertexFormat::kUnorm16x2;
|
|
||||||
case wgpu::VertexFormat::Unorm16x4:
|
|
||||||
return tint::transform::VertexFormat::kUnorm16x4;
|
|
||||||
case wgpu::VertexFormat::Snorm16x2:
|
|
||||||
return tint::transform::VertexFormat::kSnorm16x2;
|
|
||||||
case wgpu::VertexFormat::Snorm16x4:
|
|
||||||
return tint::transform::VertexFormat::kSnorm16x4;
|
|
||||||
case wgpu::VertexFormat::Float16x2:
|
|
||||||
return tint::transform::VertexFormat::kFloat16x2;
|
|
||||||
case wgpu::VertexFormat::Float16x4:
|
|
||||||
return tint::transform::VertexFormat::kFloat16x4;
|
|
||||||
case wgpu::VertexFormat::Float32:
|
|
||||||
return tint::transform::VertexFormat::kFloat32;
|
|
||||||
case wgpu::VertexFormat::Float32x2:
|
|
||||||
return tint::transform::VertexFormat::kFloat32x2;
|
|
||||||
case wgpu::VertexFormat::Float32x3:
|
|
||||||
return tint::transform::VertexFormat::kFloat32x3;
|
|
||||||
case wgpu::VertexFormat::Float32x4:
|
|
||||||
return tint::transform::VertexFormat::kFloat32x4;
|
|
||||||
case wgpu::VertexFormat::Uint32:
|
|
||||||
return tint::transform::VertexFormat::kUint32;
|
|
||||||
case wgpu::VertexFormat::Uint32x2:
|
|
||||||
return tint::transform::VertexFormat::kUint32x2;
|
|
||||||
case wgpu::VertexFormat::Uint32x3:
|
|
||||||
return tint::transform::VertexFormat::kUint32x3;
|
|
||||||
case wgpu::VertexFormat::Uint32x4:
|
|
||||||
return tint::transform::VertexFormat::kUint32x4;
|
|
||||||
case wgpu::VertexFormat::Sint32:
|
|
||||||
return tint::transform::VertexFormat::kSint32;
|
|
||||||
case wgpu::VertexFormat::Sint32x2:
|
|
||||||
return tint::transform::VertexFormat::kSint32x2;
|
|
||||||
case wgpu::VertexFormat::Sint32x3:
|
|
||||||
return tint::transform::VertexFormat::kSint32x3;
|
|
||||||
case wgpu::VertexFormat::Sint32x4:
|
|
||||||
return tint::transform::VertexFormat::kSint32x4;
|
|
||||||
|
|
||||||
case wgpu::VertexFormat::Undefined:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
tint::transform::VertexStepMode ToTintVertexStepMode(wgpu::VertexStepMode mode) {
|
|
||||||
switch (mode) {
|
|
||||||
case wgpu::VertexStepMode::Vertex:
|
|
||||||
return tint::transform::VertexStepMode::kVertex;
|
|
||||||
case wgpu::VertexStepMode::Instance:
|
|
||||||
return tint::transform::VertexStepMode::kInstance;
|
|
||||||
case wgpu::VertexStepMode::VertexBufferNotUsed:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultOrError<SingleShaderStage> TintPipelineStageToShaderStage(
|
ResultOrError<SingleShaderStage> TintPipelineStageToShaderStage(
|
||||||
tint::inspector::PipelineStage stage) {
|
tint::inspector::PipelineStage stage) {
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
|
@ -1088,39 +1007,6 @@ ResultOrError<tint::Program> RunTransforms(tint::transform::Transform* transform
|
||||||
return std::move(output.program);
|
return std::move(output.program);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddVertexPullingTransformConfig(const RenderPipelineBase& renderPipeline,
|
|
||||||
const std::string& entryPoint,
|
|
||||||
BindGroupIndex pullingBufferBindingSet,
|
|
||||||
tint::transform::DataMap* transformInputs) {
|
|
||||||
tint::transform::VertexPulling::Config cfg;
|
|
||||||
cfg.entry_point_name = entryPoint;
|
|
||||||
cfg.pulling_group = static_cast<uint32_t>(pullingBufferBindingSet);
|
|
||||||
|
|
||||||
cfg.vertex_state.resize(renderPipeline.GetVertexBufferCount());
|
|
||||||
for (VertexBufferSlot slot : IterateBitSet(renderPipeline.GetVertexBufferSlotsUsed())) {
|
|
||||||
const VertexBufferInfo& dawnInfo = renderPipeline.GetVertexBuffer(slot);
|
|
||||||
tint::transform::VertexBufferLayoutDescriptor* tintInfo =
|
|
||||||
&cfg.vertex_state[static_cast<uint8_t>(slot)];
|
|
||||||
|
|
||||||
tintInfo->array_stride = dawnInfo.arrayStride;
|
|
||||||
tintInfo->step_mode = ToTintVertexStepMode(dawnInfo.stepMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (VertexAttributeLocation location :
|
|
||||||
IterateBitSet(renderPipeline.GetAttributeLocationsUsed())) {
|
|
||||||
const VertexAttributeInfo& dawnInfo = renderPipeline.GetAttribute(location);
|
|
||||||
tint::transform::VertexAttributeDescriptor tintInfo;
|
|
||||||
tintInfo.format = ToTintVertexFormat(dawnInfo.format);
|
|
||||||
tintInfo.offset = dawnInfo.offset;
|
|
||||||
tintInfo.shader_location = static_cast<uint32_t>(static_cast<uint8_t>(location));
|
|
||||||
|
|
||||||
uint8_t vertexBufferSlot = static_cast<uint8_t>(dawnInfo.vertexBufferSlot);
|
|
||||||
cfg.vertex_state[vertexBufferSlot].attributes.push_back(tintInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
transformInputs->Add<tint::transform::VertexPulling::Config>(cfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError ValidateCompatibilityWithPipelineLayout(DeviceBase* device,
|
MaybeError ValidateCompatibilityWithPipelineLayout(DeviceBase* device,
|
||||||
const EntryPointMetadata& entryPoint,
|
const EntryPointMetadata& entryPoint,
|
||||||
const PipelineLayoutBase* layout) {
|
const PipelineLayoutBase* layout) {
|
||||||
|
@ -1306,29 +1192,6 @@ OwnedCompilationMessages* ShaderModuleBase::GetCompilationMessages() const {
|
||||||
return mCompilationMessages.get();
|
return mCompilationMessages.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
void ShaderModuleBase::AddExternalTextureTransform(const PipelineLayoutBase* layout,
|
|
||||||
tint::transform::Manager* transformManager,
|
|
||||||
tint::transform::DataMap* transformInputs) {
|
|
||||||
tint::transform::MultiplanarExternalTexture::BindingsMap newBindingsMap;
|
|
||||||
for (BindGroupIndex i : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
|
||||||
const BindGroupLayoutBase* bgl = layout->GetBindGroupLayout(i);
|
|
||||||
|
|
||||||
for (const auto& expansion : bgl->GetExternalTextureBindingExpansionMap()) {
|
|
||||||
newBindingsMap[{static_cast<uint32_t>(i),
|
|
||||||
static_cast<uint32_t>(expansion.second.plane0)}] = {
|
|
||||||
{static_cast<uint32_t>(i), static_cast<uint32_t>(expansion.second.plane1)},
|
|
||||||
{static_cast<uint32_t>(i), static_cast<uint32_t>(expansion.second.params)}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newBindingsMap.empty()) {
|
|
||||||
transformManager->Add<tint::transform::MultiplanarExternalTexture>();
|
|
||||||
transformInputs->Add<tint::transform::MultiplanarExternalTexture::NewBindingPoints>(
|
|
||||||
newBindingsMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError ShaderModuleBase::InitializeBase(ShaderModuleParseResult* parseResult,
|
MaybeError ShaderModuleBase::InitializeBase(ShaderModuleParseResult* parseResult,
|
||||||
OwnedCompilationMessages* compilationMessages) {
|
OwnedCompilationMessages* compilationMessages) {
|
||||||
mTintProgram = std::move(parseResult->tintProgram);
|
mTintProgram = std::move(parseResult->tintProgram);
|
||||||
|
|
|
@ -116,12 +116,6 @@ ResultOrError<tint::Program> RunTransforms(tint::transform::Transform* transform
|
||||||
tint::transform::DataMap* outputs,
|
tint::transform::DataMap* outputs,
|
||||||
OwnedCompilationMessages* messages);
|
OwnedCompilationMessages* messages);
|
||||||
|
|
||||||
/// Creates and adds the tint::transform::VertexPulling::Config to transformInputs.
|
|
||||||
void AddVertexPullingTransformConfig(const RenderPipelineBase& renderPipeline,
|
|
||||||
const std::string& entryPoint,
|
|
||||||
BindGroupIndex pullingBufferBindingSet,
|
|
||||||
tint::transform::DataMap* transformInputs);
|
|
||||||
|
|
||||||
// Mirrors wgpu::SamplerBindingLayout but instead stores a single boolean
|
// Mirrors wgpu::SamplerBindingLayout but instead stores a single boolean
|
||||||
// for isComparison instead of a wgpu::SamplerBindingType enum.
|
// for isComparison instead of a wgpu::SamplerBindingType enum.
|
||||||
struct ShaderSamplerBindingInfo {
|
struct ShaderSamplerBindingInfo {
|
||||||
|
@ -295,10 +289,6 @@ class ShaderModuleBase : public ApiObjectBase, public CachedObject {
|
||||||
MaybeError InitializeBase(ShaderModuleParseResult* parseResult,
|
MaybeError InitializeBase(ShaderModuleParseResult* parseResult,
|
||||||
OwnedCompilationMessages* compilationMessages);
|
OwnedCompilationMessages* compilationMessages);
|
||||||
|
|
||||||
static void AddExternalTextureTransform(const PipelineLayoutBase* layout,
|
|
||||||
tint::transform::Manager* transformManager,
|
|
||||||
tint::transform::DataMap* transformInputs);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
|
|
||||||
|
|
|
@ -59,4 +59,41 @@ void stream::Stream<tint::transform::BindingPoints>::Write(
|
||||||
StreamIn(sink, points.plane_1, points.params);
|
StreamIn(sink, points.plane_1, points.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void stream::Stream<tint::transform::VertexPulling::Config>::Write(
|
||||||
|
stream::Sink* sink,
|
||||||
|
const tint::transform::VertexPulling::Config& cfg) {
|
||||||
|
StreamIn(sink, cfg.entry_point_name, cfg.vertex_state, cfg.pulling_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void stream::Stream<tint::transform::VertexBufferLayoutDescriptor>::Write(
|
||||||
|
stream::Sink* sink,
|
||||||
|
const tint::transform::VertexBufferLayoutDescriptor& layout) {
|
||||||
|
using Layout = tint::transform::VertexBufferLayoutDescriptor;
|
||||||
|
static_assert(offsetof(Layout, array_stride) == 0,
|
||||||
|
"Please update serialization for tint::transform::VertexBufferLayoutDescriptor");
|
||||||
|
static_assert(offsetof(Layout, step_mode) == 4,
|
||||||
|
"Please update serialization for tint::transform::VertexBufferLayoutDescriptor");
|
||||||
|
static_assert(offsetof(Layout, attributes) == 8,
|
||||||
|
"Please update serialization for tint::transform::VertexBufferLayoutDescriptor");
|
||||||
|
StreamIn(sink, layout.array_stride, layout.step_mode, layout.attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void stream::Stream<tint::transform::VertexAttributeDescriptor>::Write(
|
||||||
|
stream::Sink* sink,
|
||||||
|
const tint::transform::VertexAttributeDescriptor& attrib) {
|
||||||
|
using Attrib = tint::transform::VertexAttributeDescriptor;
|
||||||
|
static_assert(offsetof(Attrib, format) == 0,
|
||||||
|
"Please update serialization for tint::transform::VertexAttributeDescriptor");
|
||||||
|
static_assert(offsetof(Attrib, offset) == 4,
|
||||||
|
"Please update serialization for tint::transform::VertexAttributeDescriptor");
|
||||||
|
static_assert(offsetof(Attrib, shader_location) == 8,
|
||||||
|
"Please update serialization for tint::transform::VertexAttributeDescriptor");
|
||||||
|
static_assert(sizeof(Attrib) == 12,
|
||||||
|
"Please update serialization for tint::transform::VertexAttributeDescriptor");
|
||||||
|
StreamIn(sink, attrib.format, attrib.offset, attrib.shader_location);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn::native
|
} // namespace dawn::native
|
||||||
|
|
|
@ -14,7 +14,10 @@
|
||||||
|
|
||||||
#include "dawn/native/TintUtils.h"
|
#include "dawn/native/TintUtils.h"
|
||||||
|
|
||||||
|
#include "dawn/native/BindGroupLayout.h"
|
||||||
#include "dawn/native/Device.h"
|
#include "dawn/native/Device.h"
|
||||||
|
#include "dawn/native/PipelineLayout.h"
|
||||||
|
#include "dawn/native/RenderPipeline.h"
|
||||||
|
|
||||||
#include "tint/tint.h"
|
#include "tint/tint.h"
|
||||||
|
|
||||||
|
@ -35,6 +38,87 @@ bool InitializeTintErrorReporter() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tint::transform::VertexFormat ToTintVertexFormat(wgpu::VertexFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case wgpu::VertexFormat::Uint8x2:
|
||||||
|
return tint::transform::VertexFormat::kUint8x2;
|
||||||
|
case wgpu::VertexFormat::Uint8x4:
|
||||||
|
return tint::transform::VertexFormat::kUint8x4;
|
||||||
|
case wgpu::VertexFormat::Sint8x2:
|
||||||
|
return tint::transform::VertexFormat::kSint8x2;
|
||||||
|
case wgpu::VertexFormat::Sint8x4:
|
||||||
|
return tint::transform::VertexFormat::kSint8x4;
|
||||||
|
case wgpu::VertexFormat::Unorm8x2:
|
||||||
|
return tint::transform::VertexFormat::kUnorm8x2;
|
||||||
|
case wgpu::VertexFormat::Unorm8x4:
|
||||||
|
return tint::transform::VertexFormat::kUnorm8x4;
|
||||||
|
case wgpu::VertexFormat::Snorm8x2:
|
||||||
|
return tint::transform::VertexFormat::kSnorm8x2;
|
||||||
|
case wgpu::VertexFormat::Snorm8x4:
|
||||||
|
return tint::transform::VertexFormat::kSnorm8x4;
|
||||||
|
case wgpu::VertexFormat::Uint16x2:
|
||||||
|
return tint::transform::VertexFormat::kUint16x2;
|
||||||
|
case wgpu::VertexFormat::Uint16x4:
|
||||||
|
return tint::transform::VertexFormat::kUint16x4;
|
||||||
|
case wgpu::VertexFormat::Sint16x2:
|
||||||
|
return tint::transform::VertexFormat::kSint16x2;
|
||||||
|
case wgpu::VertexFormat::Sint16x4:
|
||||||
|
return tint::transform::VertexFormat::kSint16x4;
|
||||||
|
case wgpu::VertexFormat::Unorm16x2:
|
||||||
|
return tint::transform::VertexFormat::kUnorm16x2;
|
||||||
|
case wgpu::VertexFormat::Unorm16x4:
|
||||||
|
return tint::transform::VertexFormat::kUnorm16x4;
|
||||||
|
case wgpu::VertexFormat::Snorm16x2:
|
||||||
|
return tint::transform::VertexFormat::kSnorm16x2;
|
||||||
|
case wgpu::VertexFormat::Snorm16x4:
|
||||||
|
return tint::transform::VertexFormat::kSnorm16x4;
|
||||||
|
case wgpu::VertexFormat::Float16x2:
|
||||||
|
return tint::transform::VertexFormat::kFloat16x2;
|
||||||
|
case wgpu::VertexFormat::Float16x4:
|
||||||
|
return tint::transform::VertexFormat::kFloat16x4;
|
||||||
|
case wgpu::VertexFormat::Float32:
|
||||||
|
return tint::transform::VertexFormat::kFloat32;
|
||||||
|
case wgpu::VertexFormat::Float32x2:
|
||||||
|
return tint::transform::VertexFormat::kFloat32x2;
|
||||||
|
case wgpu::VertexFormat::Float32x3:
|
||||||
|
return tint::transform::VertexFormat::kFloat32x3;
|
||||||
|
case wgpu::VertexFormat::Float32x4:
|
||||||
|
return tint::transform::VertexFormat::kFloat32x4;
|
||||||
|
case wgpu::VertexFormat::Uint32:
|
||||||
|
return tint::transform::VertexFormat::kUint32;
|
||||||
|
case wgpu::VertexFormat::Uint32x2:
|
||||||
|
return tint::transform::VertexFormat::kUint32x2;
|
||||||
|
case wgpu::VertexFormat::Uint32x3:
|
||||||
|
return tint::transform::VertexFormat::kUint32x3;
|
||||||
|
case wgpu::VertexFormat::Uint32x4:
|
||||||
|
return tint::transform::VertexFormat::kUint32x4;
|
||||||
|
case wgpu::VertexFormat::Sint32:
|
||||||
|
return tint::transform::VertexFormat::kSint32;
|
||||||
|
case wgpu::VertexFormat::Sint32x2:
|
||||||
|
return tint::transform::VertexFormat::kSint32x2;
|
||||||
|
case wgpu::VertexFormat::Sint32x3:
|
||||||
|
return tint::transform::VertexFormat::kSint32x3;
|
||||||
|
case wgpu::VertexFormat::Sint32x4:
|
||||||
|
return tint::transform::VertexFormat::kSint32x4;
|
||||||
|
|
||||||
|
case wgpu::VertexFormat::Undefined:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
tint::transform::VertexStepMode ToTintVertexStepMode(wgpu::VertexStepMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case wgpu::VertexStepMode::Vertex:
|
||||||
|
return tint::transform::VertexStepMode::kVertex;
|
||||||
|
case wgpu::VertexStepMode::Instance:
|
||||||
|
return tint::transform::VertexStepMode::kInstance;
|
||||||
|
case wgpu::VertexStepMode::VertexBufferNotUsed:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ScopedTintICEHandler::ScopedTintICEHandler(DeviceBase* device) {
|
ScopedTintICEHandler::ScopedTintICEHandler(DeviceBase* device) {
|
||||||
|
@ -53,6 +137,52 @@ ScopedTintICEHandler::~ScopedTintICEHandler() {
|
||||||
tlDevice = nullptr;
|
tlDevice = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tint::transform::MultiplanarExternalTexture::BindingsMap BuildExternalTextureTransformBindings(
|
||||||
|
const PipelineLayoutBase* layout) {
|
||||||
|
tint::transform::MultiplanarExternalTexture::BindingsMap newBindingsMap;
|
||||||
|
for (BindGroupIndex i : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
||||||
|
const BindGroupLayoutBase* bgl = layout->GetBindGroupLayout(i);
|
||||||
|
for (const auto& [_, expansion] : bgl->GetExternalTextureBindingExpansionMap()) {
|
||||||
|
newBindingsMap[{static_cast<uint32_t>(i), static_cast<uint32_t>(expansion.plane0)}] = {
|
||||||
|
{static_cast<uint32_t>(i), static_cast<uint32_t>(expansion.plane1)},
|
||||||
|
{static_cast<uint32_t>(i), static_cast<uint32_t>(expansion.params)}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newBindingsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
tint::transform::VertexPulling::Config BuildVertexPullingTransformConfig(
|
||||||
|
const RenderPipelineBase& renderPipeline,
|
||||||
|
const std::string_view& entryPoint,
|
||||||
|
BindGroupIndex pullingBufferBindingSet) {
|
||||||
|
tint::transform::VertexPulling::Config cfg;
|
||||||
|
cfg.entry_point_name = entryPoint;
|
||||||
|
cfg.pulling_group = static_cast<uint32_t>(pullingBufferBindingSet);
|
||||||
|
|
||||||
|
cfg.vertex_state.resize(renderPipeline.GetVertexBufferCount());
|
||||||
|
for (VertexBufferSlot slot : IterateBitSet(renderPipeline.GetVertexBufferSlotsUsed())) {
|
||||||
|
const VertexBufferInfo& dawnInfo = renderPipeline.GetVertexBuffer(slot);
|
||||||
|
tint::transform::VertexBufferLayoutDescriptor* tintInfo =
|
||||||
|
&cfg.vertex_state[static_cast<uint8_t>(slot)];
|
||||||
|
|
||||||
|
tintInfo->array_stride = dawnInfo.arrayStride;
|
||||||
|
tintInfo->step_mode = ToTintVertexStepMode(dawnInfo.stepMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (VertexAttributeLocation location :
|
||||||
|
IterateBitSet(renderPipeline.GetAttributeLocationsUsed())) {
|
||||||
|
const VertexAttributeInfo& dawnInfo = renderPipeline.GetAttribute(location);
|
||||||
|
tint::transform::VertexAttributeDescriptor tintInfo;
|
||||||
|
tintInfo.format = ToTintVertexFormat(dawnInfo.format);
|
||||||
|
tintInfo.offset = dawnInfo.offset;
|
||||||
|
tintInfo.shader_location = static_cast<uint32_t>(static_cast<uint8_t>(location));
|
||||||
|
|
||||||
|
uint8_t vertexBufferSlot = static_cast<uint8_t>(dawnInfo.vertexBufferSlot);
|
||||||
|
cfg.vertex_state[vertexBufferSlot].attributes.push_back(tintInfo);
|
||||||
|
}
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn::native
|
} // namespace dawn::native
|
||||||
|
|
||||||
bool std::less<tint::sem::BindingPoint>::operator()(const tint::sem::BindingPoint& a,
|
bool std::less<tint::sem::BindingPoint>::operator()(const tint::sem::BindingPoint& a,
|
||||||
|
|
|
@ -18,14 +18,15 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "dawn/common/NonCopyable.h"
|
#include "dawn/common/NonCopyable.h"
|
||||||
|
#include "dawn/native/IntegerTypes.h"
|
||||||
|
|
||||||
namespace tint::sem {
|
#include "tint/tint.h"
|
||||||
struct BindingPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace dawn::native {
|
namespace dawn::native {
|
||||||
|
|
||||||
class DeviceBase;
|
class DeviceBase;
|
||||||
|
class PipelineLayoutBase;
|
||||||
|
class RenderPipelineBase;
|
||||||
|
|
||||||
// Indicates that for the lifetime of this object tint internal compiler errors should be
|
// Indicates that for the lifetime of this object tint internal compiler errors should be
|
||||||
// reported to the given device.
|
// reported to the given device.
|
||||||
|
@ -38,6 +39,14 @@ class ScopedTintICEHandler : public NonCopyable {
|
||||||
ScopedTintICEHandler(ScopedTintICEHandler&&) = delete;
|
ScopedTintICEHandler(ScopedTintICEHandler&&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
tint::transform::MultiplanarExternalTexture::BindingsMap BuildExternalTextureTransformBindings(
|
||||||
|
const PipelineLayoutBase* layout);
|
||||||
|
|
||||||
|
tint::transform::VertexPulling::Config BuildVertexPullingTransformConfig(
|
||||||
|
const RenderPipelineBase& renderPipeline,
|
||||||
|
const std::string_view& entryPoint,
|
||||||
|
BindGroupIndex pullingBufferBindingSet);
|
||||||
|
|
||||||
} // namespace dawn::native
|
} // namespace dawn::native
|
||||||
|
|
||||||
// std::less operator for std::map containing BindingPoint
|
// std::less operator for std::map containing BindingPoint
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright 2022 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef SRC_DAWN_NATIVE_VISITABLEMEMBERS_H_
|
||||||
|
#define SRC_DAWN_NATIVE_VISITABLEMEMBERS_H_
|
||||||
|
|
||||||
|
#include "dawn/native/stream/Stream.h"
|
||||||
|
|
||||||
|
// Helper for X macro to declare a visitable member.
|
||||||
|
#define DAWN_INTERNAL_VISITABLE_MEMBER_DECL(type, name) type name{};
|
||||||
|
|
||||||
|
// Helper for X macro for visiting a visitable member.
|
||||||
|
#define DAWN_INTERNAL_VISITABLE_MEMBER_ARG(type, name) , name
|
||||||
|
|
||||||
|
namespace dawn::native::detail {
|
||||||
|
constexpr int kInternalVisitableUnusedForComma = 0;
|
||||||
|
} // namespace dawn::native::detail
|
||||||
|
|
||||||
|
// Helper X macro to declare members of a class or struct, along with Visit
|
||||||
|
// methods to call a functor for each member.
|
||||||
|
// Example usage:
|
||||||
|
// #define MEMBERS(X) \
|
||||||
|
// X(int, a) \
|
||||||
|
// X(float, b) \
|
||||||
|
// X(Foo, foo) \
|
||||||
|
// X(Bar, bar)
|
||||||
|
// struct MyStruct {
|
||||||
|
// DAWN_VISITABLE_MEMBERS(MEMBERS)
|
||||||
|
// };
|
||||||
|
// #undef MEMBERS
|
||||||
|
#define DAWN_VISITABLE_MEMBERS(MEMBERS) \
|
||||||
|
MEMBERS(DAWN_INTERNAL_VISITABLE_MEMBER_DECL) \
|
||||||
|
\
|
||||||
|
template <typename V> \
|
||||||
|
constexpr auto VisitAll(V&& visit) const { \
|
||||||
|
return [&](int, const auto&... ms) { \
|
||||||
|
return visit(ms...); \
|
||||||
|
}(::dawn::native::detail::kInternalVisitableUnusedForComma MEMBERS( \
|
||||||
|
DAWN_INTERNAL_VISITABLE_MEMBER_ARG)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename V> \
|
||||||
|
constexpr auto VisitAll(V&& visit) { \
|
||||||
|
return [&](int, auto&... ms) { \
|
||||||
|
return visit(ms...); \
|
||||||
|
}(::dawn::native::detail::kInternalVisitableUnusedForComma MEMBERS( \
|
||||||
|
DAWN_INTERNAL_VISITABLE_MEMBER_ARG)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SRC_DAWN_NATIVE_VISITABLEMEMBERS_H_
|
|
@ -756,7 +756,12 @@ ResultOrError<CompiledShader> ShaderModule::Compile(const ProgrammableStage& pro
|
||||||
const tint::Program* program = GetTintProgram();
|
const tint::Program* program = GetTintProgram();
|
||||||
tint::Program programAsValue;
|
tint::Program programAsValue;
|
||||||
|
|
||||||
AddExternalTextureTransform(layout, &transformManager, &transformInputs);
|
auto externalTextureBindings = BuildExternalTextureTransformBindings(layout);
|
||||||
|
if (!externalTextureBindings.empty()) {
|
||||||
|
transformManager.Add<tint::transform::MultiplanarExternalTexture>();
|
||||||
|
transformInputs.Add<tint::transform::MultiplanarExternalTexture::NewBindingPoints>(
|
||||||
|
std::move(externalTextureBindings));
|
||||||
|
}
|
||||||
|
|
||||||
if (stage == SingleShaderStage::Vertex) {
|
if (stage == SingleShaderStage::Vertex) {
|
||||||
transformManager.Add<tint::transform::FirstIndexOffset>();
|
transformManager.Add<tint::transform::FirstIndexOffset>();
|
||||||
|
|
|
@ -55,15 +55,6 @@ class ShaderModule final : public ShaderModuleBase {
|
||||||
const RenderPipeline* renderPipeline = nullptr);
|
const RenderPipeline* renderPipeline = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResultOrError<std::string> TranslateToMSL(const char* entryPointName,
|
|
||||||
SingleShaderStage stage,
|
|
||||||
const PipelineLayout* layout,
|
|
||||||
uint32_t sampleMask,
|
|
||||||
const RenderPipeline* renderPipeline,
|
|
||||||
std::string* remappedEntryPointName,
|
|
||||||
bool* needsStorageBufferLength,
|
|
||||||
bool* hasInvariantAttribute,
|
|
||||||
std::vector<uint32_t>* workgroupAllocations);
|
|
||||||
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
|
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
|
||||||
~ShaderModule() override;
|
~ShaderModule() override;
|
||||||
MaybeError Initialize(ShaderModuleParseResult* parseResult,
|
MaybeError Initialize(ShaderModuleParseResult* parseResult,
|
||||||
|
|
|
@ -15,10 +15,14 @@
|
||||||
#include "dawn/native/metal/ShaderModuleMTL.h"
|
#include "dawn/native/metal/ShaderModuleMTL.h"
|
||||||
|
|
||||||
#include "dawn/native/BindGroupLayout.h"
|
#include "dawn/native/BindGroupLayout.h"
|
||||||
|
#include "dawn/native/CacheRequest.h"
|
||||||
#include "dawn/native/TintUtils.h"
|
#include "dawn/native/TintUtils.h"
|
||||||
|
#include "dawn/native/VisitableMembers.h"
|
||||||
#include "dawn/native/metal/DeviceMTL.h"
|
#include "dawn/native/metal/DeviceMTL.h"
|
||||||
#include "dawn/native/metal/PipelineLayoutMTL.h"
|
#include "dawn/native/metal/PipelineLayoutMTL.h"
|
||||||
#include "dawn/native/metal/RenderPipelineMTL.h"
|
#include "dawn/native/metal/RenderPipelineMTL.h"
|
||||||
|
#include "dawn/native/stream/BlobSource.h"
|
||||||
|
#include "dawn/native/stream/ByteVectorSink.h"
|
||||||
#include "dawn/platform/DawnPlatform.h"
|
#include "dawn/platform/DawnPlatform.h"
|
||||||
#include "dawn/platform/tracing/TraceEvent.h"
|
#include "dawn/platform/tracing/TraceEvent.h"
|
||||||
|
|
||||||
|
@ -26,6 +30,67 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace dawn::native::metal {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using OptionalVertexPullingTransformConfig = std::optional<tint::transform::VertexPulling::Config>;
|
||||||
|
|
||||||
|
#define MSL_COMPILATION_REQUEST_MEMBERS(X) \
|
||||||
|
X(const tint::Program*, inputProgram) \
|
||||||
|
X(tint::transform::BindingRemapper::BindingPoints, bindingPoints) \
|
||||||
|
X(tint::transform::MultiplanarExternalTexture::BindingsMap, externalTextureBindings) \
|
||||||
|
X(OptionalVertexPullingTransformConfig, vertexPullingTransformConfig) \
|
||||||
|
X(std::string, entryPointName) \
|
||||||
|
X(uint32_t, sampleMask) \
|
||||||
|
X(bool, emitVertexPointSize) \
|
||||||
|
X(bool, isRobustnessEnabled) \
|
||||||
|
X(bool, disableSymbolRenaming) \
|
||||||
|
X(bool, disableWorkgroupInit) \
|
||||||
|
X(CacheKey::UnsafeUnkeyedValue<dawn::platform::Platform*>, tracePlatform)
|
||||||
|
|
||||||
|
DAWN_MAKE_CACHE_REQUEST(MslCompilationRequest, MSL_COMPILATION_REQUEST_MEMBERS);
|
||||||
|
#undef MSL_COMPILATION_REQUEST_MEMBERS
|
||||||
|
|
||||||
|
using WorkgroupAllocations = std::vector<uint32_t>;
|
||||||
|
|
||||||
|
#define MSL_COMPILATION_MEMBERS(X) \
|
||||||
|
X(std::string, msl) \
|
||||||
|
X(std::string, remappedEntryPointName) \
|
||||||
|
X(bool, needsStorageBufferLength) \
|
||||||
|
X(bool, hasInvariantAttribute) \
|
||||||
|
X(WorkgroupAllocations, workgroupAllocations)
|
||||||
|
|
||||||
|
struct MslCompilation {
|
||||||
|
static ResultOrError<MslCompilation> FromBlob(Blob blob);
|
||||||
|
|
||||||
|
DAWN_VISITABLE_MEMBERS(MSL_COMPILATION_MEMBERS)
|
||||||
|
#undef MSL_COMPILATION_MEMBERS
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace dawn::native::metal
|
||||||
|
|
||||||
|
namespace dawn::native {
|
||||||
|
|
||||||
|
// Define the implementation to store MslCompilation into the BlobCache.
|
||||||
|
template <>
|
||||||
|
void BlobCache::Store<metal::MslCompilation>(const CacheKey& key, const metal::MslCompilation& c) {
|
||||||
|
stream::ByteVectorSink sink;
|
||||||
|
c.VisitAll([&](const auto&... members) { StreamIn(&sink, members...); });
|
||||||
|
Store(key, CreateBlob(std::move(sink)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the implementation to load MslCompilation from a blob.
|
||||||
|
// static
|
||||||
|
ResultOrError<metal::MslCompilation> metal::MslCompilation::FromBlob(Blob blob) {
|
||||||
|
stream::BlobSource source(std::move(blob));
|
||||||
|
metal::MslCompilation c;
|
||||||
|
DAWN_TRY(c.VisitAll([&](auto&... members) { return StreamOut(&source, &members...); }));
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::native
|
||||||
|
|
||||||
namespace dawn::native::metal {
|
namespace dawn::native::metal {
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -50,17 +115,16 @@ MaybeError ShaderModule::Initialize(ShaderModuleParseResult* parseResult,
|
||||||
return InitializeBase(parseResult, compilationMessages);
|
return InitializeBase(parseResult, compilationMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<std::string> ShaderModule::TranslateToMSL(
|
namespace {
|
||||||
const char* entryPointName,
|
|
||||||
SingleShaderStage stage,
|
ResultOrError<CacheResult<MslCompilation>> TranslateToMSL(DeviceBase* device,
|
||||||
const PipelineLayout* layout,
|
const tint::Program* inputProgram,
|
||||||
uint32_t sampleMask,
|
const char* entryPointName,
|
||||||
const RenderPipeline* renderPipeline,
|
SingleShaderStage stage,
|
||||||
std::string* remappedEntryPointName,
|
const PipelineLayout* layout,
|
||||||
bool* needsStorageBufferLength,
|
uint32_t sampleMask,
|
||||||
bool* hasInvariantAttribute,
|
const RenderPipeline* renderPipeline) {
|
||||||
std::vector<uint32_t>* workgroupAllocations) {
|
ScopedTintICEHandler scopedICEHandler(device);
|
||||||
ScopedTintICEHandler scopedICEHandler(GetDevice());
|
|
||||||
|
|
||||||
std::ostringstream errorStream;
|
std::ostringstream errorStream;
|
||||||
errorStream << "Tint MSL failure:" << std::endl;
|
errorStream << "Tint MSL failure:" << std::endl;
|
||||||
|
@ -69,7 +133,6 @@ ResultOrError<std::string> ShaderModule::TranslateToMSL(
|
||||||
using BindingRemapper = tint::transform::BindingRemapper;
|
using BindingRemapper = tint::transform::BindingRemapper;
|
||||||
using BindingPoint = tint::transform::BindingPoint;
|
using BindingPoint = tint::transform::BindingPoint;
|
||||||
BindingRemapper::BindingPoints bindingPoints;
|
BindingRemapper::BindingPoints bindingPoints;
|
||||||
BindingRemapper::AccessControls accessControls;
|
|
||||||
|
|
||||||
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
||||||
const BindGroupLayoutBase::BindingMap& bindingMap =
|
const BindGroupLayoutBase::BindingMap& bindingMap =
|
||||||
|
@ -93,21 +156,13 @@ ResultOrError<std::string> ShaderModule::TranslateToMSL(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tint::transform::Manager transformManager;
|
auto externalTextureBindings = BuildExternalTextureTransformBindings(layout);
|
||||||
tint::transform::DataMap transformInputs;
|
|
||||||
|
|
||||||
// We only remap bindings for the target entry point, so we need to strip all other entry
|
|
||||||
// points to avoid generating invalid bindings for them.
|
|
||||||
transformManager.Add<tint::transform::SingleEntryPoint>();
|
|
||||||
transformInputs.Add<tint::transform::SingleEntryPoint::Config>(entryPointName);
|
|
||||||
|
|
||||||
AddExternalTextureTransform(layout, &transformManager, &transformInputs);
|
|
||||||
|
|
||||||
|
std::optional<tint::transform::VertexPulling::Config> vertexPullingTransformConfig;
|
||||||
if (stage == SingleShaderStage::Vertex &&
|
if (stage == SingleShaderStage::Vertex &&
|
||||||
GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling)) {
|
device->IsToggleEnabled(Toggle::MetalEnableVertexPulling)) {
|
||||||
transformManager.Add<tint::transform::VertexPulling>();
|
vertexPullingTransformConfig = BuildVertexPullingTransformConfig(
|
||||||
AddVertexPullingTransformConfig(*renderPipeline, entryPointName, kPullingBufferBindingSet,
|
*renderPipeline, entryPointName, kPullingBufferBindingSet);
|
||||||
&transformInputs);
|
|
||||||
|
|
||||||
for (VertexBufferSlot slot : IterateBitSet(renderPipeline->GetVertexBufferSlotsUsed())) {
|
for (VertexBufferSlot slot : IterateBitSet(renderPipeline->GetVertexBufferSlotsUsed())) {
|
||||||
uint32_t metalIndex = renderPipeline->GetMtlVertexBufferIndex(slot);
|
uint32_t metalIndex = renderPipeline->GetMtlVertexBufferIndex(slot);
|
||||||
|
@ -121,62 +176,127 @@ ResultOrError<std::string> ShaderModule::TranslateToMSL(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GetDevice()->IsRobustnessEnabled()) {
|
|
||||||
transformManager.Add<tint::transform::Robustness>();
|
|
||||||
}
|
|
||||||
transformManager.Add<tint::transform::BindingRemapper>();
|
|
||||||
transformManager.Add<tint::transform::Renamer>();
|
|
||||||
|
|
||||||
if (GetDevice()->IsToggleEnabled(Toggle::DisableSymbolRenaming)) {
|
MslCompilationRequest req = {};
|
||||||
// We still need to rename MSL reserved keywords
|
req.inputProgram = inputProgram;
|
||||||
transformInputs.Add<tint::transform::Renamer::Config>(
|
req.bindingPoints = std::move(bindingPoints);
|
||||||
tint::transform::Renamer::Target::kMslKeywords);
|
req.externalTextureBindings = std::move(externalTextureBindings);
|
||||||
}
|
req.vertexPullingTransformConfig = std::move(vertexPullingTransformConfig);
|
||||||
|
req.entryPointName = entryPointName;
|
||||||
transformInputs.Add<BindingRemapper::Remappings>(std::move(bindingPoints),
|
req.sampleMask = sampleMask;
|
||||||
std::move(accessControls),
|
req.emitVertexPointSize =
|
||||||
/* mayCollide */ true);
|
|
||||||
|
|
||||||
tint::Program program;
|
|
||||||
tint::transform::DataMap transformOutputs;
|
|
||||||
{
|
|
||||||
TRACE_EVENT0(GetDevice()->GetPlatform(), General, "RunTransforms");
|
|
||||||
DAWN_TRY_ASSIGN(program, RunTransforms(&transformManager, GetTintProgram(), transformInputs,
|
|
||||||
&transformOutputs, nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* data = transformOutputs.Get<tint::transform::Renamer::Data>()) {
|
|
||||||
auto it = data->remappings.find(entryPointName);
|
|
||||||
if (it != data->remappings.end()) {
|
|
||||||
*remappedEntryPointName = it->second;
|
|
||||||
} else {
|
|
||||||
DAWN_INVALID_IF(!GetDevice()->IsToggleEnabled(Toggle::DisableSymbolRenaming),
|
|
||||||
"Could not find remapped name for entry point.");
|
|
||||||
|
|
||||||
*remappedEntryPointName = entryPointName;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return DAWN_FORMAT_VALIDATION_ERROR("Transform output missing renamer data.");
|
|
||||||
}
|
|
||||||
|
|
||||||
tint::writer::msl::Options options;
|
|
||||||
options.buffer_size_ubo_index = kBufferLengthBufferSlot;
|
|
||||||
options.fixed_sample_mask = sampleMask;
|
|
||||||
options.disable_workgroup_init = GetDevice()->IsToggleEnabled(Toggle::DisableWorkgroupInit);
|
|
||||||
options.emit_vertex_point_size =
|
|
||||||
stage == SingleShaderStage::Vertex &&
|
stage == SingleShaderStage::Vertex &&
|
||||||
renderPipeline->GetPrimitiveTopology() == wgpu::PrimitiveTopology::PointList;
|
renderPipeline->GetPrimitiveTopology() == wgpu::PrimitiveTopology::PointList;
|
||||||
TRACE_EVENT0(GetDevice()->GetPlatform(), General, "tint::writer::msl::Generate");
|
req.isRobustnessEnabled = device->IsRobustnessEnabled();
|
||||||
auto result = tint::writer::msl::Generate(&program, options);
|
req.disableSymbolRenaming = device->IsToggleEnabled(Toggle::DisableSymbolRenaming);
|
||||||
DAWN_INVALID_IF(!result.success, "An error occured while generating MSL: %s.", result.error);
|
req.tracePlatform = UnsafeUnkeyedValue(device->GetPlatform());
|
||||||
|
|
||||||
*needsStorageBufferLength = result.needs_storage_buffer_sizes;
|
CacheResult<MslCompilation> mslCompilation;
|
||||||
*hasInvariantAttribute = result.has_invariant_attribute;
|
DAWN_TRY_LOAD_OR_RUN(
|
||||||
*workgroupAllocations = std::move(result.workgroup_allocations[*remappedEntryPointName]);
|
mslCompilation, device, std::move(req), MslCompilation::FromBlob,
|
||||||
|
[](MslCompilationRequest r) -> ResultOrError<MslCompilation> {
|
||||||
|
tint::transform::Manager transformManager;
|
||||||
|
tint::transform::DataMap transformInputs;
|
||||||
|
|
||||||
return std::move(result.msl);
|
// We only remap bindings for the target entry point, so we need to strip all other
|
||||||
|
// entry points to avoid generating invalid bindings for them.
|
||||||
|
transformManager.Add<tint::transform::SingleEntryPoint>();
|
||||||
|
transformInputs.Add<tint::transform::SingleEntryPoint::Config>(r.entryPointName);
|
||||||
|
|
||||||
|
if (!r.externalTextureBindings.empty()) {
|
||||||
|
transformManager.Add<tint::transform::MultiplanarExternalTexture>();
|
||||||
|
transformInputs.Add<tint::transform::MultiplanarExternalTexture::NewBindingPoints>(
|
||||||
|
std::move(r.externalTextureBindings));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r.vertexPullingTransformConfig) {
|
||||||
|
transformManager.Add<tint::transform::VertexPulling>();
|
||||||
|
transformInputs.Add<tint::transform::VertexPulling::Config>(
|
||||||
|
std::move(r.vertexPullingTransformConfig).value());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r.isRobustnessEnabled) {
|
||||||
|
transformManager.Add<tint::transform::Robustness>();
|
||||||
|
}
|
||||||
|
transformManager.Add<BindingRemapper>();
|
||||||
|
transformInputs.Add<BindingRemapper::Remappings>(std::move(r.bindingPoints),
|
||||||
|
BindingRemapper::AccessControls{},
|
||||||
|
/* mayCollide */ true);
|
||||||
|
|
||||||
|
transformManager.Add<tint::transform::Renamer>();
|
||||||
|
|
||||||
|
if (r.disableSymbolRenaming) {
|
||||||
|
// We still need to rename MSL reserved keywords
|
||||||
|
transformInputs.Add<tint::transform::Renamer::Config>(
|
||||||
|
tint::transform::Renamer::Target::kMslKeywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
tint::Program program;
|
||||||
|
tint::transform::DataMap transformOutputs;
|
||||||
|
{
|
||||||
|
TRACE_EVENT0(r.tracePlatform.UnsafeGetValue(), General, "RunTransforms");
|
||||||
|
DAWN_TRY_ASSIGN(program,
|
||||||
|
RunTransforms(&transformManager, r.inputProgram, transformInputs,
|
||||||
|
&transformOutputs, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string remappedEntryPointName;
|
||||||
|
if (auto* data = transformOutputs.Get<tint::transform::Renamer::Data>()) {
|
||||||
|
auto it = data->remappings.find(r.entryPointName);
|
||||||
|
if (it != data->remappings.end()) {
|
||||||
|
remappedEntryPointName = it->second;
|
||||||
|
} else {
|
||||||
|
DAWN_INVALID_IF(!r.disableSymbolRenaming,
|
||||||
|
"Could not find remapped name for entry point.");
|
||||||
|
|
||||||
|
remappedEntryPointName = r.entryPointName;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return DAWN_FORMAT_VALIDATION_ERROR("Transform output missing renamer data.");
|
||||||
|
}
|
||||||
|
|
||||||
|
tint::writer::msl::Options options;
|
||||||
|
options.buffer_size_ubo_index = kBufferLengthBufferSlot;
|
||||||
|
options.fixed_sample_mask = r.sampleMask;
|
||||||
|
options.disable_workgroup_init = r.disableWorkgroupInit;
|
||||||
|
options.emit_vertex_point_size = r.emitVertexPointSize;
|
||||||
|
TRACE_EVENT0(r.tracePlatform.UnsafeGetValue(), General, "tint::writer::msl::Generate");
|
||||||
|
auto result = tint::writer::msl::Generate(&program, options);
|
||||||
|
DAWN_INVALID_IF(!result.success, "An error occured while generating MSL: %s.",
|
||||||
|
result.error);
|
||||||
|
|
||||||
|
// Metal uses Clang to compile the shader as C++14. Disable everything in the -Wall
|
||||||
|
// category. -Wunused-variable in particular comes up a lot in generated code, and some
|
||||||
|
// (old?) Metal drivers accidentally treat it as a MTLLibraryErrorCompileError instead
|
||||||
|
// of a warning.
|
||||||
|
result.msl = R"(
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic ignored "-Wall"
|
||||||
|
#endif
|
||||||
|
)" + result.msl;
|
||||||
|
|
||||||
|
auto workgroupAllocations =
|
||||||
|
std::move(result.workgroup_allocations[remappedEntryPointName]);
|
||||||
|
return MslCompilation{
|
||||||
|
std::move(result.msl),
|
||||||
|
std::move(remappedEntryPointName),
|
||||||
|
result.needs_storage_buffer_sizes,
|
||||||
|
result.has_invariant_attribute,
|
||||||
|
std::move(workgroupAllocations),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (device->IsToggleEnabled(Toggle::DumpShaders)) {
|
||||||
|
std::ostringstream dumpedMsg;
|
||||||
|
dumpedMsg << "/* Dumped generated MSL */" << std::endl << mslCompilation->msl;
|
||||||
|
device->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return mslCompilation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
MaybeError ShaderModule::CreateFunction(const char* entryPointName,
|
MaybeError ShaderModule::CreateFunction(const char* entryPointName,
|
||||||
SingleShaderStage stage,
|
SingleShaderStage stage,
|
||||||
const PipelineLayout* layout,
|
const PipelineLayout* layout,
|
||||||
|
@ -194,33 +314,17 @@ MaybeError ShaderModule::CreateFunction(const char* entryPointName,
|
||||||
ASSERT(renderPipeline != nullptr);
|
ASSERT(renderPipeline != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string remappedEntryPointName;
|
CacheResult<MslCompilation> mslCompilation;
|
||||||
std::string msl;
|
DAWN_TRY_ASSIGN(mslCompilation, TranslateToMSL(GetDevice(), GetTintProgram(), entryPointName,
|
||||||
bool hasInvariantAttribute = false;
|
stage, layout, sampleMask, renderPipeline));
|
||||||
DAWN_TRY_ASSIGN(msl, TranslateToMSL(entryPointName, stage, layout, sampleMask, renderPipeline,
|
out->needsStorageBufferLength = mslCompilation->needsStorageBufferLength;
|
||||||
&remappedEntryPointName, &out->needsStorageBufferLength,
|
out->workgroupAllocations = std::move(mslCompilation->workgroupAllocations);
|
||||||
&hasInvariantAttribute, &out->workgroupAllocations));
|
|
||||||
|
|
||||||
// Metal uses Clang to compile the shader as C++14. Disable everything in the -Wall
|
NSRef<NSString> mslSource =
|
||||||
// category. -Wunused-variable in particular comes up a lot in generated code, and some
|
AcquireNSRef([[NSString alloc] initWithUTF8String:mslCompilation->msl.c_str()]);
|
||||||
// (old?) Metal drivers accidentally treat it as a MTLLibraryErrorCompileError instead
|
|
||||||
// of a warning.
|
|
||||||
msl = R"(
|
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic ignored "-Wall"
|
|
||||||
#endif
|
|
||||||
)" + msl;
|
|
||||||
|
|
||||||
if (GetDevice()->IsToggleEnabled(Toggle::DumpShaders)) {
|
|
||||||
std::ostringstream dumpedMsg;
|
|
||||||
dumpedMsg << "/* Dumped generated MSL */" << std::endl << msl;
|
|
||||||
GetDevice()->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
NSRef<NSString> mslSource = AcquireNSRef([[NSString alloc] initWithUTF8String:msl.c_str()]);
|
|
||||||
|
|
||||||
NSRef<MTLCompileOptions> compileOptions = AcquireNSRef([[MTLCompileOptions alloc] init]);
|
NSRef<MTLCompileOptions> compileOptions = AcquireNSRef([[MTLCompileOptions alloc] init]);
|
||||||
if (hasInvariantAttribute) {
|
if (mslCompilation->hasInvariantAttribute) {
|
||||||
if (@available(macOS 11.0, iOS 13.0, *)) {
|
if (@available(macOS 11.0, iOS 13.0, *)) {
|
||||||
(*compileOptions).preserveInvariance = true;
|
(*compileOptions).preserveInvariance = true;
|
||||||
}
|
}
|
||||||
|
@ -243,8 +347,8 @@ MaybeError ShaderModule::CreateFunction(const char* entryPointName,
|
||||||
}
|
}
|
||||||
ASSERT(library != nil);
|
ASSERT(library != nil);
|
||||||
|
|
||||||
NSRef<NSString> name =
|
NSRef<NSString> name = AcquireNSRef(
|
||||||
AcquireNSRef([[NSString alloc] initWithUTF8String:remappedEntryPointName.c_str()]);
|
[[NSString alloc] initWithUTF8String:mslCompilation->remappedEntryPointName.c_str()]);
|
||||||
|
|
||||||
{
|
{
|
||||||
TRACE_EVENT0(GetDevice()->GetPlatform(), General, "MTLLibrary::newFunctionWithName");
|
TRACE_EVENT0(GetDevice()->GetPlatform(), General, "MTLLibrary::newFunctionWithName");
|
||||||
|
@ -269,6 +373,10 @@ MaybeError ShaderModule::CreateFunction(const char* entryPointName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BlobCache* cache = GetDevice()->GetBlobCache()) {
|
||||||
|
cache->EnsureStored(mslCompilation);
|
||||||
|
}
|
||||||
|
|
||||||
if (GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling) &&
|
if (GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling) &&
|
||||||
GetEntryPoint(entryPointName).usedVertexInputs.any()) {
|
GetEntryPoint(entryPointName).usedVertexInputs.any()) {
|
||||||
out->needsStorageBufferLength = true;
|
out->needsStorageBufferLength = true;
|
||||||
|
|
|
@ -90,7 +90,12 @@ ResultOrError<std::string> ShaderModule::TranslateToGLSL(const char* entryPointN
|
||||||
tint::transform::Manager transformManager;
|
tint::transform::Manager transformManager;
|
||||||
tint::transform::DataMap transformInputs;
|
tint::transform::DataMap transformInputs;
|
||||||
|
|
||||||
AddExternalTextureTransform(layout, &transformManager, &transformInputs);
|
auto externalTextureBindings = BuildExternalTextureTransformBindings(layout);
|
||||||
|
if (!externalTextureBindings.empty()) {
|
||||||
|
transformManager.Add<tint::transform::MultiplanarExternalTexture>();
|
||||||
|
transformInputs.Add<tint::transform::MultiplanarExternalTexture::NewBindingPoints>(
|
||||||
|
std::move(externalTextureBindings));
|
||||||
|
}
|
||||||
|
|
||||||
tint::Program program;
|
tint::Program program;
|
||||||
DAWN_TRY_ASSIGN(program, RunTransforms(&transformManager, GetTintProgram(), transformInputs,
|
DAWN_TRY_ASSIGN(program, RunTransforms(&transformManager, GetTintProgram(), transformInputs,
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "dawn/common/Platform.h"
|
#include "dawn/common/Platform.h"
|
||||||
#include "dawn/common/TypedInteger.h"
|
#include "dawn/common/TypedInteger.h"
|
||||||
#include "dawn/native/Error.h"
|
#include "dawn/native/Error.h"
|
||||||
|
@ -57,6 +59,14 @@ MaybeError StreamOut(Source* s, T* v) {
|
||||||
return Stream<T>::Read(s, v);
|
return Stream<T>::Read(s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper to take an rvalue passed to StreamOut and forward it as a pointer.
|
||||||
|
// This makes it possible to pass output wrappers like stream::StructMembers inline.
|
||||||
|
// For example: `DAWN_TRY(StreamOut(&source, stream::StructMembers(...)));`
|
||||||
|
template <typename T>
|
||||||
|
MaybeError StreamOut(Source* s, T&& v) {
|
||||||
|
return StreamOut(s, &v);
|
||||||
|
}
|
||||||
|
|
||||||
// Helper to call StreamIn on a parameter pack.
|
// Helper to call StreamIn on a parameter pack.
|
||||||
template <typename T, typename... Ts>
|
template <typename T, typename... Ts>
|
||||||
constexpr void StreamIn(Sink* s, const T& v, const Ts&... vs) {
|
constexpr void StreamIn(Sink* s, const T& v, const Ts&... vs) {
|
||||||
|
@ -187,6 +197,19 @@ class Stream<T, std::enable_if_t<std::is_pointer_v<T>>> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Stream specialization for std::optional
|
||||||
|
template <typename T>
|
||||||
|
class Stream<std::optional<T>> {
|
||||||
|
public:
|
||||||
|
static void Write(stream::Sink* sink, const std::optional<T>& t) {
|
||||||
|
bool hasValue = t.has_value();
|
||||||
|
StreamIn(sink, hasValue);
|
||||||
|
if (hasValue) {
|
||||||
|
StreamIn(sink, *t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Stream specialization for fixed arrays of fundamental types.
|
// Stream specialization for fixed arrays of fundamental types.
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
class Stream<T[N], std::enable_if_t<std::is_fundamental_v<T>>> {
|
class Stream<T[N], std::enable_if_t<std::is_fundamental_v<T>>> {
|
||||||
|
|
|
@ -232,7 +232,7 @@ ResultOrError<ShaderModule::ModuleAndSpirv> ShaderModule::GetHandleAndSpirv(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform external textures into the binding locations specified in the bgl
|
// Transform external textures into the binding locations specified in the bgl
|
||||||
// TODO(dawn:1082): Replace this block with ShaderModuleBase::AddExternalTextureTransform.
|
// TODO(dawn:1082): Replace this block with BuildExternalTextureTransformBindings.
|
||||||
tint::transform::MultiplanarExternalTexture::BindingsMap newBindingsMap;
|
tint::transform::MultiplanarExternalTexture::BindingsMap newBindingsMap;
|
||||||
for (BindGroupIndex i : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
for (BindGroupIndex i : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
||||||
const BindGroupLayoutBase* bgl = layout->GetBindGroupLayout(i);
|
const BindGroupLayoutBase* bgl = layout->GetBindGroupLayout(i);
|
||||||
|
|
|
@ -108,8 +108,8 @@ class PipelineCachingTests : public DawnTest {
|
||||||
const EntryCounts counts = {
|
const EntryCounts counts = {
|
||||||
// pipeline caching is only implemented on D3D12/Vulkan
|
// pipeline caching is only implemented on D3D12/Vulkan
|
||||||
IsD3D12() || IsVulkan() ? 1u : 0u,
|
IsD3D12() || IsVulkan() ? 1u : 0u,
|
||||||
// shader module caching is only implemented on Vulkan
|
// shader module caching is only implemented on Vulkan/Metal
|
||||||
IsVulkan() ? 1u : 0u,
|
IsVulkan() || IsMetal() ? 1u : 0u,
|
||||||
};
|
};
|
||||||
NiceMock<CachingInterfaceMock> mMockCache;
|
NiceMock<CachingInterfaceMock> mMockCache;
|
||||||
};
|
};
|
||||||
|
@ -406,7 +406,7 @@ TEST_P(SinglePipelineCachingTests, RenderPipelineBlobCacheDescriptorNegativeCase
|
||||||
{
|
{
|
||||||
wgpu::Device device = CreateDevice();
|
wgpu::Device device = CreateDevice();
|
||||||
utils::ComboRenderPipelineDescriptor desc;
|
utils::ComboRenderPipelineDescriptor desc;
|
||||||
desc.primitive.topology = wgpu::PrimitiveTopology::PointList;
|
desc.EnableDepthStencil();
|
||||||
desc.vertex.module = utils::CreateShaderModule(device, kVertexShaderDefault.data());
|
desc.vertex.module = utils::CreateShaderModule(device, kVertexShaderDefault.data());
|
||||||
desc.vertex.entryPoint = "main";
|
desc.vertex.entryPoint = "main";
|
||||||
desc.cFragment.module = utils::CreateShaderModule(device, kFragmentShaderDefault.data());
|
desc.cFragment.module = utils::CreateShaderModule(device, kFragmentShaderDefault.data());
|
||||||
|
@ -586,8 +586,9 @@ TEST_P(SinglePipelineCachingTests, RenderPipelineBlobCacheLayout) {
|
||||||
device.CreateRenderPipeline(&desc));
|
device.CreateRenderPipeline(&desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache should hit for the shaders, but not for the pipeline.
|
// Cache should not hit for the fragment shader, but should hit for the pipeline.
|
||||||
// The shader is different but compiles to the same due to binding number remapping.
|
// Except for D3D12, the shader is different but compiles to the same due to binding number
|
||||||
|
// remapping.
|
||||||
{
|
{
|
||||||
wgpu::Device device = CreateDevice();
|
wgpu::Device device = CreateDevice();
|
||||||
utils::ComboRenderPipelineDescriptor desc;
|
utils::ComboRenderPipelineDescriptor desc;
|
||||||
|
@ -604,8 +605,14 @@ TEST_P(SinglePipelineCachingTests, RenderPipelineBlobCacheLayout) {
|
||||||
{1, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Uniform},
|
{1, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Uniform},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
EXPECT_CACHE_STATS(mMockCache, Hit(2 * counts.shaderModule), Add(counts.pipeline),
|
if (!IsD3D12()) {
|
||||||
device.CreateRenderPipeline(&desc));
|
EXPECT_CACHE_STATS(mMockCache, Hit(counts.shaderModule + counts.pipeline),
|
||||||
|
Add(counts.shaderModule), device.CreateRenderPipeline(&desc));
|
||||||
|
} else {
|
||||||
|
EXPECT_CACHE_STATS(mMockCache, Hit(counts.shaderModule),
|
||||||
|
Add(counts.shaderModule + counts.pipeline),
|
||||||
|
device.CreateRenderPipeline(&desc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "dawn/common/TypedInteger.h"
|
#include "dawn/common/TypedInteger.h"
|
||||||
#include "dawn/native/Blob.h"
|
#include "dawn/native/Blob.h"
|
||||||
|
#include "dawn/native/VisitableMembers.h"
|
||||||
#include "dawn/native/stream/BlobSource.h"
|
#include "dawn/native/stream/BlobSource.h"
|
||||||
#include "dawn/native/stream/ByteVectorSink.h"
|
#include "dawn/native/stream/ByteVectorSink.h"
|
||||||
#include "dawn/native/stream/Stream.h"
|
#include "dawn/native/stream/Stream.h"
|
||||||
|
@ -193,6 +194,23 @@ TEST(SerializeTests, StdPair) {
|
||||||
EXPECT_CACHE_KEY_EQ(std::make_pair(s, uint32_t(42)), expected);
|
EXPECT_CACHE_KEY_EQ(std::make_pair(s, uint32_t(42)), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that ByteVectorSink serializes std::optional as expected.
|
||||||
|
TEST(SerializeTests, StdOptional) {
|
||||||
|
std::string_view s = "webgpu";
|
||||||
|
{
|
||||||
|
ByteVectorSink expected;
|
||||||
|
StreamIn(&expected, true, s);
|
||||||
|
|
||||||
|
EXPECT_CACHE_KEY_EQ(std::optional(s), expected);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ByteVectorSink expected;
|
||||||
|
StreamIn(&expected, false);
|
||||||
|
|
||||||
|
EXPECT_CACHE_KEY_EQ(std::optional<std::string_view>(), expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test that ByteVectorSink serializes std::unordered_map as expected.
|
// Test that ByteVectorSink serializes std::unordered_map as expected.
|
||||||
TEST(SerializeTests, StdUnorderedMap) {
|
TEST(SerializeTests, StdUnorderedMap) {
|
||||||
std::unordered_map<uint32_t, std::string_view> m;
|
std::unordered_map<uint32_t, std::string_view> m;
|
||||||
|
@ -256,6 +274,41 @@ TEST(StreamTests, SerializeDeserializeParamPack) {
|
||||||
EXPECT_EQ(c, cOut);
|
EXPECT_EQ(c, cOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FOO_MEMBERS(X) \
|
||||||
|
X(int, a) \
|
||||||
|
X(float, b) \
|
||||||
|
X(std::string, c)
|
||||||
|
struct Foo {
|
||||||
|
DAWN_VISITABLE_MEMBERS(FOO_MEMBERS)
|
||||||
|
#undef FOO_MEMBERS
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test that serializing then deserializing a struct made with DAWN_VISITABLE_MEMBERS works as
|
||||||
|
// expected.
|
||||||
|
TEST(StreamTests, SerializeDeserializeVisitableMembers) {
|
||||||
|
Foo foo{1, 2, "3"};
|
||||||
|
ByteVectorSink sink;
|
||||||
|
foo.VisitAll([&](const auto&... members) { StreamIn(&sink, members...); });
|
||||||
|
|
||||||
|
// Test that the serialization is correct.
|
||||||
|
{
|
||||||
|
ByteVectorSink expected;
|
||||||
|
StreamIn(&expected, foo.a, foo.b, foo.c);
|
||||||
|
EXPECT_THAT(sink, VectorEq(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that deserialization works for StructMembers, passed inline.
|
||||||
|
{
|
||||||
|
BlobSource src(CreateBlob(sink));
|
||||||
|
Foo out;
|
||||||
|
auto err = out.VisitAll([&](auto&... members) { return StreamOut(&src, &members...); });
|
||||||
|
EXPECT_FALSE(err.IsError());
|
||||||
|
EXPECT_EQ(foo.a, out.a);
|
||||||
|
EXPECT_EQ(foo.b, out.b);
|
||||||
|
EXPECT_EQ(foo.c, out.c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
std::bitset<N - 1> BitsetFromBitString(const char (&str)[N]) {
|
std::bitset<N - 1> BitsetFromBitString(const char (&str)[N]) {
|
||||||
// N - 1 because the last character is the null terminator.
|
// N - 1 because the last character is the null terminator.
|
||||||
|
|
Loading…
Reference in New Issue