dawn-cmake/src/transform/array_length_from_uniform.h
James Price 960aa2ee75 msl: Add ArrayLengthFromUniform transform
Generate a uniform buffer that will receive the lengths of all storage
buffers, and use this to implement calls to arrayLength(). The
transform is provided with a set of mappings from storage buffer
binding points to the corresponding index into the array of buffer
lengths. The transform reports whether it generated the uniform
buffers or not.

Use this transform from the MSL sanitizer, using the binding number as
the index into the array. This matches the behavior of spirv-cross,
and so works with how Dawn already produces this uniform buffer.

Bug: tint:256
Change-Id: I2682d2d024e8daa30f78270b8cfb6bbb32632133
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54480
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
2021-06-19 00:33:35 +00:00

105 lines
3.4 KiB
C++

// Copyright 2021 The Tint 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_TRANSFORM_ARRAY_LENGTH_FROM_UNIFORM_H_
#define SRC_TRANSFORM_ARRAY_LENGTH_FROM_UNIFORM_H_
#include <unordered_map>
#include "src/sem/binding_point.h"
#include "src/transform/transform.h"
namespace tint {
// Forward declarations
class CloneContext;
namespace transform {
/// ArrayLengthFromUniform is a transform that implements calls to arrayLength()
/// by calculating the length from the total size of the storage buffer, which
/// is received via a uniform buffer.
///
/// The generated uniform buffer will have the form:
/// ```
/// [[block]]
/// struct buffer_size_struct {
/// buffer_size : array<u32, 8>;
/// };
///
/// [[group(0), binding(30)]]
/// var<uniform> buffer_size_ubo : buffer_size_struct;
/// ```
/// The binding group and number used for this uniform buffer is provided via
/// the `Config` transform input. The `Config` struct also defines the mapping
/// from a storage buffer's `BindingPoint` to the array index that will be used
/// to get the size of that buffer.
///
/// This transform assumes that the `InlinePointerLets` and `Simplify`
/// transforms have been run before it so that arguments to the arrayLength
/// builtin always have the form `&resource.array`.
class ArrayLengthFromUniform : public Transform {
public:
/// Constructor
ArrayLengthFromUniform();
/// Destructor
~ArrayLengthFromUniform() override;
/// Configuration options for the ArrayLengthFromUniform transform.
struct Config : public Castable<Data, transform::Data> {
/// Constructor
/// @param ubo_bp the binding point to use for the generated uniform buffer.
explicit Config(sem::BindingPoint ubo_bp);
/// Copy constructor
Config(const Config&);
/// Destructor
~Config() override;
/// The binding point to use for the generated uniform buffer.
sem::BindingPoint ubo_binding;
/// The mapping from binding point to the index for the buffer size lookup.
std::unordered_map<sem::BindingPoint, uint32_t> bindpoint_to_size_index;
};
/// Information produced about what the transform did.
struct Result : public Castable<Result, transform::Data> {
/// Constructor
/// @param needs_sizes True if the transform generated the buffer sizes UBO.
explicit Result(bool needs_sizes);
/// Copy constructor
Result(const Result&);
/// Destructor
~Result() override;
/// True if the transform generated the buffer sizes UBO.
bool const needs_buffer_sizes;
};
/// Runs the transform on `program`, returning the transformation result.
/// @param program the source program to transform
/// @param data optional extra transform-specific data
/// @returns the transformation result
Output Run(const Program* program, const DataMap& data = {}) override;
};
} // namespace transform
} // namespace tint
#endif // SRC_TRANSFORM_ARRAY_LENGTH_FROM_UNIFORM_H_