writer/hlsl: Emit UBO as an array of vector
Instead of a ConstantBuffer. HLSL requires that each structure field in a UBO is 16 byte aligned. WGSL has much looser constraints with its UBO field alignment rules. Instead generate an array of uint4 vectors, and index into this, much like we index into [RW]ByteAddressBuffers for SSBOs. Extend the DecomposeStorageAccess transform to support uniforms too. This has been renamed to DecomposeMemoryAccess. Change-Id: I3868ff80af1ab3b3dddfbf5b969724cb87ef0744 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/55246 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
9efc4fcc89
commit
165512c57e
|
@ -556,8 +556,8 @@ libtint_source_set("libtint_core_all_src") {
|
||||||
"transform/calculate_array_length.h",
|
"transform/calculate_array_length.h",
|
||||||
"transform/canonicalize_entry_point_io.cc",
|
"transform/canonicalize_entry_point_io.cc",
|
||||||
"transform/canonicalize_entry_point_io.h",
|
"transform/canonicalize_entry_point_io.h",
|
||||||
"transform/decompose_storage_access.cc",
|
"transform/decompose_memory_access.cc",
|
||||||
"transform/decompose_storage_access.h",
|
"transform/decompose_memory_access.h",
|
||||||
"transform/external_texture_transform.cc",
|
"transform/external_texture_transform.cc",
|
||||||
"transform/external_texture_transform.h",
|
"transform/external_texture_transform.h",
|
||||||
"transform/first_index_offset.cc",
|
"transform/first_index_offset.cc",
|
||||||
|
|
|
@ -281,8 +281,8 @@ set(TINT_LIB_SRCS
|
||||||
transform/calculate_array_length.h
|
transform/calculate_array_length.h
|
||||||
transform/canonicalize_entry_point_io.cc
|
transform/canonicalize_entry_point_io.cc
|
||||||
transform/canonicalize_entry_point_io.h
|
transform/canonicalize_entry_point_io.h
|
||||||
transform/decompose_storage_access.cc
|
transform/decompose_memory_access.cc
|
||||||
transform/decompose_storage_access.h
|
transform/decompose_memory_access.h
|
||||||
transform/external_texture_transform.cc
|
transform/external_texture_transform.cc
|
||||||
transform/external_texture_transform.h
|
transform/external_texture_transform.h
|
||||||
transform/first_index_offset.cc
|
transform/first_index_offset.cc
|
||||||
|
@ -860,7 +860,7 @@ if(${TINT_BUILD_TESTS})
|
||||||
transform/bound_array_accessors_test.cc
|
transform/bound_array_accessors_test.cc
|
||||||
transform/calculate_array_length_test.cc
|
transform/calculate_array_length_test.cc
|
||||||
transform/canonicalize_entry_point_io_test.cc
|
transform/canonicalize_entry_point_io_test.cc
|
||||||
transform/decompose_storage_access_test.cc
|
transform/decompose_memory_access_test.cc
|
||||||
transform/external_texture_transform_test.cc
|
transform/external_texture_transform_test.cc
|
||||||
transform/first_index_offset_test.cc
|
transform/first_index_offset_test.cc
|
||||||
transform/fold_constants_test.cc
|
transform/fold_constants_test.cc
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "src/transform/decompose_storage_access.h"
|
#include "src/transform/decompose_memory_access.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
#include "src/utils/get_or_create.h"
|
#include "src/utils/get_or_create.h"
|
||||||
#include "src/utils/hash.h"
|
#include "src/utils/hash.h"
|
||||||
|
|
||||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::DecomposeStorageAccess::Intrinsic);
|
TINT_INSTANTIATE_TYPEINFO(tint::transform::DecomposeMemoryAccess::Intrinsic);
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace transform {
|
namespace transform {
|
||||||
|
@ -46,7 +46,7 @@ namespace transform {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// Offset is a simple ast::Expression builder interface, used to build byte
|
/// Offset is a simple ast::Expression builder interface, used to build byte
|
||||||
/// offsets for storage buffer accesses.
|
/// offsets for storage and uniform buffer accesses.
|
||||||
struct Offset : Castable<Offset> {
|
struct Offset : Castable<Offset> {
|
||||||
/// @returns builds and returns the ast::Expression in `ctx.dst`
|
/// @returns builds and returns the ast::Expression in `ctx.dst`
|
||||||
virtual ast::Expression* Build(CloneContext& ctx) = 0;
|
virtual ast::Expression* Build(CloneContext& ctx) = 0;
|
||||||
|
@ -179,14 +179,16 @@ std::unique_ptr<Offset> Mul(LHS&& lhs_, RHS&& rhs_) {
|
||||||
|
|
||||||
/// LoadStoreKey is the unordered map key to a load or store intrinsic.
|
/// LoadStoreKey is the unordered map key to a load or store intrinsic.
|
||||||
struct LoadStoreKey {
|
struct LoadStoreKey {
|
||||||
|
ast::StorageClass const storage_class; // buffer storage class
|
||||||
sem::Type const* buf_ty; // buffer type
|
sem::Type const* buf_ty; // buffer type
|
||||||
sem::Type const* el_ty; // element type
|
sem::Type const* el_ty; // element type
|
||||||
bool operator==(const LoadStoreKey& rhs) const {
|
bool operator==(const LoadStoreKey& rhs) const {
|
||||||
return buf_ty == rhs.buf_ty && el_ty == rhs.el_ty;
|
return storage_class == rhs.storage_class && buf_ty == rhs.buf_ty &&
|
||||||
|
el_ty == rhs.el_ty;
|
||||||
}
|
}
|
||||||
struct Hasher {
|
struct Hasher {
|
||||||
inline std::size_t operator()(const LoadStoreKey& u) const {
|
inline std::size_t operator()(const LoadStoreKey& u) const {
|
||||||
return utils::Hash(u.buf_ty, u.el_ty);
|
return utils::Hash(u.storage_class, u.buf_ty, u.el_ty);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -218,60 +220,60 @@ uint32_t MatrixColumnStride(const sem::Matrix* mat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntrinsicDataTypeFor(const sem::Type* ty,
|
bool IntrinsicDataTypeFor(const sem::Type* ty,
|
||||||
DecomposeStorageAccess::Intrinsic::DataType& out) {
|
DecomposeMemoryAccess::Intrinsic::DataType& out) {
|
||||||
if (ty->Is<sem::I32>()) {
|
if (ty->Is<sem::I32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kI32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kI32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ty->Is<sem::U32>()) {
|
if (ty->Is<sem::U32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kU32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kU32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ty->Is<sem::F32>()) {
|
if (ty->Is<sem::F32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kF32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kF32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (auto* vec = ty->As<sem::Vector>()) {
|
if (auto* vec = ty->As<sem::Vector>()) {
|
||||||
switch (vec->size()) {
|
switch (vec->size()) {
|
||||||
case 2:
|
case 2:
|
||||||
if (vec->type()->Is<sem::I32>()) {
|
if (vec->type()->Is<sem::I32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kVec2I32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec2I32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (vec->type()->Is<sem::U32>()) {
|
if (vec->type()->Is<sem::U32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kVec2U32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec2U32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (vec->type()->Is<sem::F32>()) {
|
if (vec->type()->Is<sem::F32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kVec2F32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec2F32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (vec->type()->Is<sem::I32>()) {
|
if (vec->type()->Is<sem::I32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kVec3I32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec3I32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (vec->type()->Is<sem::U32>()) {
|
if (vec->type()->Is<sem::U32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kVec3U32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec3U32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (vec->type()->Is<sem::F32>()) {
|
if (vec->type()->Is<sem::F32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kVec3F32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec3F32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (vec->type()->Is<sem::I32>()) {
|
if (vec->type()->Is<sem::I32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kVec4I32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec4I32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (vec->type()->Is<sem::U32>()) {
|
if (vec->type()->Is<sem::U32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kVec4U32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec4U32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (vec->type()->Is<sem::F32>()) {
|
if (vec->type()->Is<sem::F32>()) {
|
||||||
out = DecomposeStorageAccess::Intrinsic::DataType::kVec4F32;
|
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec4F32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -282,80 +284,86 @@ bool IntrinsicDataTypeFor(const sem::Type* ty,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied
|
/// @returns a DecomposeMemoryAccess::Intrinsic decoration that can be applied
|
||||||
/// to a stub function to load the type `ty`.
|
/// to a stub function to load the type `ty`.
|
||||||
DecomposeStorageAccess::Intrinsic* IntrinsicLoadFor(ProgramBuilder* builder,
|
DecomposeMemoryAccess::Intrinsic* IntrinsicLoadFor(
|
||||||
|
ProgramBuilder* builder,
|
||||||
|
ast::StorageClass storage_class,
|
||||||
const sem::Type* ty) {
|
const sem::Type* ty) {
|
||||||
DecomposeStorageAccess::Intrinsic::DataType type;
|
DecomposeMemoryAccess::Intrinsic::DataType type;
|
||||||
if (!IntrinsicDataTypeFor(ty, type)) {
|
if (!IntrinsicDataTypeFor(ty, type)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return builder->ASTNodes().Create<DecomposeStorageAccess::Intrinsic>(
|
return builder->ASTNodes().Create<DecomposeMemoryAccess::Intrinsic>(
|
||||||
builder->ID(), DecomposeStorageAccess::Intrinsic::Op::kLoad, type);
|
builder->ID(), DecomposeMemoryAccess::Intrinsic::Op::kLoad, storage_class,
|
||||||
|
type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied
|
/// @returns a DecomposeMemoryAccess::Intrinsic decoration that can be applied
|
||||||
/// to a stub function to store the type `ty`.
|
/// to a stub function to store the type `ty`.
|
||||||
DecomposeStorageAccess::Intrinsic* IntrinsicStoreFor(ProgramBuilder* builder,
|
DecomposeMemoryAccess::Intrinsic* IntrinsicStoreFor(
|
||||||
|
ProgramBuilder* builder,
|
||||||
|
ast::StorageClass storage_class,
|
||||||
const sem::Type* ty) {
|
const sem::Type* ty) {
|
||||||
DecomposeStorageAccess::Intrinsic::DataType type;
|
DecomposeMemoryAccess::Intrinsic::DataType type;
|
||||||
if (!IntrinsicDataTypeFor(ty, type)) {
|
if (!IntrinsicDataTypeFor(ty, type)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return builder->ASTNodes().Create<DecomposeStorageAccess::Intrinsic>(
|
return builder->ASTNodes().Create<DecomposeMemoryAccess::Intrinsic>(
|
||||||
builder->ID(), DecomposeStorageAccess::Intrinsic::Op::kStore, type);
|
builder->ID(), DecomposeMemoryAccess::Intrinsic::Op::kStore,
|
||||||
|
storage_class, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied
|
/// @returns a DecomposeMemoryAccess::Intrinsic decoration that can be applied
|
||||||
/// to a stub function for the atomic op and the type `ty`.
|
/// to a stub function for the atomic op and the type `ty`.
|
||||||
DecomposeStorageAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder,
|
DecomposeMemoryAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder,
|
||||||
sem::IntrinsicType ity,
|
sem::IntrinsicType ity,
|
||||||
const sem::Type* ty) {
|
const sem::Type* ty) {
|
||||||
auto op = DecomposeStorageAccess::Intrinsic::Op::kAtomicLoad;
|
auto op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad;
|
||||||
switch (ity) {
|
switch (ity) {
|
||||||
case sem::IntrinsicType::kAtomicLoad:
|
case sem::IntrinsicType::kAtomicLoad:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicLoad;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicLoad;
|
||||||
break;
|
break;
|
||||||
case sem::IntrinsicType::kAtomicStore:
|
case sem::IntrinsicType::kAtomicStore:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicStore;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicStore;
|
||||||
break;
|
break;
|
||||||
case sem::IntrinsicType::kAtomicAdd:
|
case sem::IntrinsicType::kAtomicAdd:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicAdd;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAdd;
|
||||||
break;
|
break;
|
||||||
case sem::IntrinsicType::kAtomicMax:
|
case sem::IntrinsicType::kAtomicMax:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicMax;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMax;
|
||||||
break;
|
break;
|
||||||
case sem::IntrinsicType::kAtomicMin:
|
case sem::IntrinsicType::kAtomicMin:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicMin;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMin;
|
||||||
break;
|
break;
|
||||||
case sem::IntrinsicType::kAtomicAnd:
|
case sem::IntrinsicType::kAtomicAnd:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicAnd;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAnd;
|
||||||
break;
|
break;
|
||||||
case sem::IntrinsicType::kAtomicOr:
|
case sem::IntrinsicType::kAtomicOr:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicOr;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicOr;
|
||||||
break;
|
break;
|
||||||
case sem::IntrinsicType::kAtomicXor:
|
case sem::IntrinsicType::kAtomicXor:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicXor;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicXor;
|
||||||
break;
|
break;
|
||||||
case sem::IntrinsicType::kAtomicExchange:
|
case sem::IntrinsicType::kAtomicExchange:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicExchange;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicExchange;
|
||||||
break;
|
break;
|
||||||
case sem::IntrinsicType::kAtomicCompareExchangeWeak:
|
case sem::IntrinsicType::kAtomicCompareExchangeWeak:
|
||||||
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicCompareExchangeWeak;
|
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicCompareExchangeWeak;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TINT_ICE(builder->Diagnostics())
|
TINT_ICE(builder->Diagnostics())
|
||||||
<< "invalid IntrinsicType for DecomposeStorageAccess::Intrinsic: "
|
<< "invalid IntrinsicType for DecomposeMemoryAccess::Intrinsic: "
|
||||||
<< ty->type_name();
|
<< ty->type_name();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecomposeStorageAccess::Intrinsic::DataType type;
|
DecomposeMemoryAccess::Intrinsic::DataType type;
|
||||||
if (!IntrinsicDataTypeFor(ty, type)) {
|
if (!IntrinsicDataTypeFor(ty, type)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return builder->ASTNodes().Create<DecomposeStorageAccess::Intrinsic>(
|
return builder->ASTNodes().Create<DecomposeMemoryAccess::Intrinsic>(
|
||||||
builder->ID(), op, type);
|
builder->ID(), op, ast::StorageClass::kStorage, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts `node` before `insert_after` in the global declarations of
|
/// Inserts `node` before `insert_after` in the global declarations of
|
||||||
|
@ -387,30 +395,30 @@ const ast::TypeDecl* TypeDeclOf(const sem::Type* ty) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// StorageBufferAccess describes a single storage buffer access
|
/// BufferAccess describes a single storage or uniform buffer access
|
||||||
struct StorageBufferAccess {
|
struct BufferAccess {
|
||||||
sem::Expression const* var = nullptr; // Storage buffer variable
|
sem::Expression const* var = nullptr; // Storage buffer variable
|
||||||
std::unique_ptr<Offset> offset; // The byte offset on var
|
std::unique_ptr<Offset> offset; // The byte offset on var
|
||||||
sem::Type const* type = nullptr; // The type of the access
|
sem::Type const* type = nullptr; // The type of the access
|
||||||
operator bool() const { return var; } // Returns true if valid
|
operator bool() const { return var; } // Returns true if valid
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Store describes a single storage buffer write
|
/// Store describes a single storage or uniform buffer write
|
||||||
struct Store {
|
struct Store {
|
||||||
ast::AssignmentStatement* assignment; // The AST assignment statement
|
ast::AssignmentStatement* assignment; // The AST assignment statement
|
||||||
StorageBufferAccess target; // The target for the write
|
BufferAccess target; // The target for the write
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
/// State holds the current transform state
|
/// State holds the current transform state
|
||||||
struct DecomposeStorageAccess::State {
|
struct DecomposeMemoryAccess::State {
|
||||||
/// Map of AST expression to storage buffer access
|
/// Map of AST expression to storage or uniform buffer access
|
||||||
/// This map has entries added when encountered, and removed when outer
|
/// This map has entries added when encountered, and removed when outer
|
||||||
/// expressions chain the access.
|
/// expressions chain the access.
|
||||||
/// Subset of #expression_order, as expressions are not removed from
|
/// Subset of #expression_order, as expressions are not removed from
|
||||||
/// #expression_order.
|
/// #expression_order.
|
||||||
std::unordered_map<ast::Expression*, StorageBufferAccess> accesses;
|
std::unordered_map<ast::Expression*, BufferAccess> accesses;
|
||||||
/// The visited order of AST expressions (superset of #accesses)
|
/// The visited order of AST expressions (superset of #accesses)
|
||||||
std::vector<ast::Expression*> expression_order;
|
std::vector<ast::Expression*> expression_order;
|
||||||
/// [buffer-type, element-type] -> load function name
|
/// [buffer-type, element-type] -> load function name
|
||||||
|
@ -419,25 +427,25 @@ struct DecomposeStorageAccess::State {
|
||||||
std::unordered_map<LoadStoreKey, Symbol, LoadStoreKey::Hasher> store_funcs;
|
std::unordered_map<LoadStoreKey, Symbol, LoadStoreKey::Hasher> store_funcs;
|
||||||
/// [buffer-type, element-type, atomic-op] -> load function name
|
/// [buffer-type, element-type, atomic-op] -> load function name
|
||||||
std::unordered_map<AtomicKey, Symbol, AtomicKey::Hasher> atomic_funcs;
|
std::unordered_map<AtomicKey, Symbol, AtomicKey::Hasher> atomic_funcs;
|
||||||
/// List of storage buffer writes
|
/// List of storage or uniform buffer writes
|
||||||
std::vector<Store> stores;
|
std::vector<Store> stores;
|
||||||
|
|
||||||
/// AddAccess() adds the `expr -> access` map item to #accesses, and `expr`
|
/// AddAccess() adds the `expr -> access` map item to #accesses, and `expr`
|
||||||
/// to #expression_order.
|
/// to #expression_order.
|
||||||
/// @param expr the expression that performs the access
|
/// @param expr the expression that performs the access
|
||||||
/// @param access the access
|
/// @param access the access
|
||||||
void AddAccess(ast::Expression* expr, StorageBufferAccess&& access) {
|
void AddAccess(ast::Expression* expr, BufferAccess&& access) {
|
||||||
TINT_ASSERT(access.type);
|
TINT_ASSERT(access.type);
|
||||||
accesses.emplace(expr, std::move(access));
|
accesses.emplace(expr, std::move(access));
|
||||||
expression_order.emplace_back(expr);
|
expression_order.emplace_back(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TakeAccess() removes the `node` item from #accesses (if it exists),
|
/// TakeAccess() removes the `node` item from #accesses (if it exists),
|
||||||
/// returning the StorageBufferAccess. If #accesses does not hold an item for
|
/// returning the BufferAccess. If #accesses does not hold an item for
|
||||||
/// `node`, an invalid StorageBufferAccess is returned.
|
/// `node`, an invalid BufferAccess is returned.
|
||||||
/// @param node the expression that performed an access
|
/// @param node the expression that performed an access
|
||||||
/// @return the StorageBufferAccess for the given expression
|
/// @return the BufferAccess for the given expression
|
||||||
StorageBufferAccess TakeAccess(ast::Expression* node) {
|
BufferAccess TakeAccess(ast::Expression* node) {
|
||||||
auto lhs_it = accesses.find(node);
|
auto lhs_it = accesses.find(node);
|
||||||
if (lhs_it == accesses.end()) {
|
if (lhs_it == accesses.end()) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -448,12 +456,13 @@ struct DecomposeStorageAccess::State {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LoadFunc() returns a symbol to an intrinsic function that loads an element
|
/// LoadFunc() returns a symbol to an intrinsic function that loads an element
|
||||||
/// of type `el_ty` from a storage buffer of type `buf_ty`. The function has
|
/// of type `el_ty` from a storage or uniform buffer of type `buf_ty`.
|
||||||
/// the signature: `fn load(buf : buf_ty, offset : u32) -> el_ty`
|
/// The emitted function has the signature:
|
||||||
|
/// `fn load(buf : buf_ty, offset : u32) -> el_ty`
|
||||||
/// @param ctx the CloneContext
|
/// @param ctx the CloneContext
|
||||||
/// @param insert_after the user-declared type to insert the function after
|
/// @param insert_after the user-declared type to insert the function after
|
||||||
/// @param buf_ty the storage buffer type
|
/// @param buf_ty the storage or uniform buffer type
|
||||||
/// @param el_ty the storage buffer element type
|
/// @param el_ty the storage or uniform buffer element type
|
||||||
/// @param var_user the variable user
|
/// @param var_user the variable user
|
||||||
/// @return the name of the function that performs the load
|
/// @return the name of the function that performs the load
|
||||||
Symbol LoadFunc(CloneContext& ctx,
|
Symbol LoadFunc(CloneContext& ctx,
|
||||||
|
@ -461,35 +470,42 @@ struct DecomposeStorageAccess::State {
|
||||||
const sem::Type* buf_ty,
|
const sem::Type* buf_ty,
|
||||||
const sem::Type* el_ty,
|
const sem::Type* el_ty,
|
||||||
const sem::VariableUser* var_user) {
|
const sem::VariableUser* var_user) {
|
||||||
return utils::GetOrCreate(load_funcs, LoadStoreKey{buf_ty, el_ty}, [&] {
|
auto storage_class = var_user->Variable()->StorageClass();
|
||||||
|
return utils::GetOrCreate(
|
||||||
|
load_funcs, LoadStoreKey{storage_class, buf_ty, el_ty}, [&] {
|
||||||
auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty);
|
auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty);
|
||||||
|
|
||||||
ast::VariableList params = {
|
ast::VariableList params = {
|
||||||
// Note: The buffer parameter requires the kStorage StorageClass in
|
// Note: The buffer parameter requires the StorageClass in
|
||||||
// order for HLSL to emit this as a ByteAddressBuffer.
|
// order for HLSL to emit this as a ByteAddressBuffer or cbuffer
|
||||||
|
// array.
|
||||||
ctx.dst->create<ast::Variable>(
|
ctx.dst->create<ast::Variable>(
|
||||||
ctx.dst->Sym("buffer"), ast::StorageClass::kStorage,
|
ctx.dst->Sym("buffer"), storage_class,
|
||||||
var_user->Variable()->Access(), buf_ast_ty, true, nullptr,
|
var_user->Variable()->Access(), buf_ast_ty, true, nullptr,
|
||||||
ast::DecorationList{}),
|
ast::DecorationList{}),
|
||||||
ctx.dst->Param("offset", ctx.dst->ty.u32()),
|
ctx.dst->Param("offset", ctx.dst->ty.u32()),
|
||||||
};
|
};
|
||||||
|
|
||||||
ast::Function* func = nullptr;
|
ast::Function* func = nullptr;
|
||||||
if (auto* intrinsic = IntrinsicLoadFor(ctx.dst, el_ty)) {
|
if (auto* intrinsic =
|
||||||
|
IntrinsicLoadFor(ctx.dst, storage_class, el_ty)) {
|
||||||
auto* el_ast_ty = CreateASTTypeFor(&ctx, el_ty);
|
auto* el_ast_ty = CreateASTTypeFor(&ctx, el_ty);
|
||||||
func = ctx.dst->create<ast::Function>(
|
func = ctx.dst->create<ast::Function>(
|
||||||
ctx.dst->Sym(), params, el_ast_ty, nullptr,
|
ctx.dst->Sym(), params, el_ast_ty, nullptr,
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
intrinsic,
|
intrinsic,
|
||||||
ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
|
ctx.dst->ASTNodes()
|
||||||
ctx.dst->ID(), ast::DisabledValidation::kFunctionHasNoBody),
|
.Create<ast::DisableValidationDecoration>(
|
||||||
|
ctx.dst->ID(),
|
||||||
|
ast::DisabledValidation::kFunctionHasNoBody),
|
||||||
},
|
},
|
||||||
ast::DecorationList{});
|
ast::DecorationList{});
|
||||||
} else {
|
} else {
|
||||||
ast::ExpressionList values;
|
ast::ExpressionList values;
|
||||||
if (auto* mat_ty = el_ty->As<sem::Matrix>()) {
|
if (auto* mat_ty = el_ty->As<sem::Matrix>()) {
|
||||||
auto* vec_ty = mat_ty->ColumnType();
|
auto* vec_ty = mat_ty->ColumnType();
|
||||||
Symbol load = LoadFunc(ctx, insert_after, buf_ty, vec_ty, var_user);
|
Symbol load =
|
||||||
|
LoadFunc(ctx, insert_after, buf_ty, vec_ty, var_user);
|
||||||
for (uint32_t i = 0; i < mat_ty->columns(); i++) {
|
for (uint32_t i = 0; i < mat_ty->columns(); i++) {
|
||||||
auto* offset =
|
auto* offset =
|
||||||
ctx.dst->Add("offset", i * MatrixColumnStride(mat_ty));
|
ctx.dst->Add("offset", i * MatrixColumnStride(mat_ty));
|
||||||
|
@ -513,8 +529,8 @@ struct DecomposeStorageAccess::State {
|
||||||
auto* el_ast_ty = CreateASTTypeFor(&ctx, el_ty);
|
auto* el_ast_ty = CreateASTTypeFor(&ctx, el_ty);
|
||||||
func = ctx.dst->create<ast::Function>(
|
func = ctx.dst->create<ast::Function>(
|
||||||
ctx.dst->Sym(), params, el_ast_ty,
|
ctx.dst->Sym(), params, el_ast_ty,
|
||||||
ctx.dst->Block(
|
ctx.dst->Block(ctx.dst->Return(
|
||||||
ctx.dst->Return(ctx.dst->create<ast::TypeConstructorExpression>(
|
ctx.dst->create<ast::TypeConstructorExpression>(
|
||||||
CreateASTTypeFor(&ctx, el_ty), values))),
|
CreateASTTypeFor(&ctx, el_ty), values))),
|
||||||
ast::DecorationList{}, ast::DecorationList{});
|
ast::DecorationList{}, ast::DecorationList{});
|
||||||
}
|
}
|
||||||
|
@ -524,8 +540,9 @@ struct DecomposeStorageAccess::State {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// StoreFunc() returns a symbol to an intrinsic function that stores an
|
/// StoreFunc() returns a symbol to an intrinsic function that stores an
|
||||||
/// element of type `el_ty` to a storage buffer of type `buf_ty`. The function
|
/// element of type `el_ty` to a storage buffer of type `buf_ty`.
|
||||||
/// has the signature: `fn store(buf : buf_ty, offset : u32, value : el_ty)`
|
/// The function has the signature:
|
||||||
|
/// `fn store(buf : buf_ty, offset : u32, value : el_ty)`
|
||||||
/// @param ctx the CloneContext
|
/// @param ctx the CloneContext
|
||||||
/// @param insert_after the user-declared type to insert the function after
|
/// @param insert_after the user-declared type to insert the function after
|
||||||
/// @param buf_ty the storage buffer type
|
/// @param buf_ty the storage buffer type
|
||||||
|
@ -537,27 +554,32 @@ struct DecomposeStorageAccess::State {
|
||||||
const sem::Type* buf_ty,
|
const sem::Type* buf_ty,
|
||||||
const sem::Type* el_ty,
|
const sem::Type* el_ty,
|
||||||
const sem::VariableUser* var_user) {
|
const sem::VariableUser* var_user) {
|
||||||
return utils::GetOrCreate(store_funcs, LoadStoreKey{buf_ty, el_ty}, [&] {
|
auto storage_class = var_user->Variable()->StorageClass();
|
||||||
|
return utils::GetOrCreate(
|
||||||
|
store_funcs, LoadStoreKey{storage_class, buf_ty, el_ty}, [&] {
|
||||||
auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty);
|
auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty);
|
||||||
auto* el_ast_ty = CreateASTTypeFor(&ctx, el_ty);
|
auto* el_ast_ty = CreateASTTypeFor(&ctx, el_ty);
|
||||||
ast::VariableList params{
|
ast::VariableList params{
|
||||||
// Note: The buffer parameter requires the kStorage StorageClass in
|
// Note: The buffer parameter requires the StorageClass in
|
||||||
// order for HLSL to emit this as a ByteAddressBuffer.
|
// order for HLSL to emit this as a ByteAddressBuffer.
|
||||||
ctx.dst->create<ast::Variable>(
|
ctx.dst->create<ast::Variable>(
|
||||||
ctx.dst->Sym("buffer"), ast::StorageClass::kStorage,
|
ctx.dst->Sym("buffer"), storage_class,
|
||||||
var_user->Variable()->Access(), buf_ast_ty, true, nullptr,
|
var_user->Variable()->Access(), buf_ast_ty, true, nullptr,
|
||||||
ast::DecorationList{}),
|
ast::DecorationList{}),
|
||||||
ctx.dst->Param("offset", ctx.dst->ty.u32()),
|
ctx.dst->Param("offset", ctx.dst->ty.u32()),
|
||||||
ctx.dst->Param("value", el_ast_ty),
|
ctx.dst->Param("value", el_ast_ty),
|
||||||
};
|
};
|
||||||
ast::Function* func = nullptr;
|
ast::Function* func = nullptr;
|
||||||
if (auto* intrinsic = IntrinsicStoreFor(ctx.dst, el_ty)) {
|
if (auto* intrinsic =
|
||||||
|
IntrinsicStoreFor(ctx.dst, storage_class, el_ty)) {
|
||||||
func = ctx.dst->create<ast::Function>(
|
func = ctx.dst->create<ast::Function>(
|
||||||
ctx.dst->Sym(), params, ctx.dst->ty.void_(), nullptr,
|
ctx.dst->Sym(), params, ctx.dst->ty.void_(), nullptr,
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
intrinsic,
|
intrinsic,
|
||||||
ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
|
ctx.dst->ASTNodes()
|
||||||
ctx.dst->ID(), ast::DisabledValidation::kFunctionHasNoBody),
|
.Create<ast::DisableValidationDecoration>(
|
||||||
|
ctx.dst->ID(),
|
||||||
|
ast::DisabledValidation::kFunctionHasNoBody),
|
||||||
},
|
},
|
||||||
ast::DecorationList{});
|
ast::DecorationList{});
|
||||||
|
|
||||||
|
@ -565,7 +587,8 @@ struct DecomposeStorageAccess::State {
|
||||||
ast::StatementList body;
|
ast::StatementList body;
|
||||||
if (auto* mat_ty = el_ty->As<sem::Matrix>()) {
|
if (auto* mat_ty = el_ty->As<sem::Matrix>()) {
|
||||||
auto* vec_ty = mat_ty->ColumnType();
|
auto* vec_ty = mat_ty->ColumnType();
|
||||||
Symbol store = StoreFunc(ctx, insert_after, buf_ty, vec_ty, var_user);
|
Symbol store =
|
||||||
|
StoreFunc(ctx, insert_after, buf_ty, vec_ty, var_user);
|
||||||
for (uint32_t i = 0; i < mat_ty->columns(); i++) {
|
for (uint32_t i = 0; i < mat_ty->columns(); i++) {
|
||||||
auto* offset =
|
auto* offset =
|
||||||
ctx.dst->Add("offset", i * MatrixColumnStride(mat_ty));
|
ctx.dst->Add("offset", i * MatrixColumnStride(mat_ty));
|
||||||
|
@ -586,16 +609,19 @@ struct DecomposeStorageAccess::State {
|
||||||
} else if (auto* arr = el_ty->As<sem::Array>()) {
|
} else if (auto* arr = el_ty->As<sem::Array>()) {
|
||||||
for (uint32_t i = 0; i < arr->Count(); i++) {
|
for (uint32_t i = 0; i < arr->Count(); i++) {
|
||||||
auto* offset = ctx.dst->Add("offset", arr->Stride() * i);
|
auto* offset = ctx.dst->Add("offset", arr->Stride() * i);
|
||||||
auto* access = ctx.dst->IndexAccessor("value", ctx.dst->Expr(i));
|
auto* access =
|
||||||
Symbol store = StoreFunc(ctx, insert_after, buf_ty,
|
ctx.dst->IndexAccessor("value", ctx.dst->Expr(i));
|
||||||
|
Symbol store =
|
||||||
|
StoreFunc(ctx, insert_after, buf_ty,
|
||||||
arr->ElemType()->UnwrapRef(), var_user);
|
arr->ElemType()->UnwrapRef(), var_user);
|
||||||
auto* call = ctx.dst->Call(store, "buffer", offset, access);
|
auto* call = ctx.dst->Call(store, "buffer", offset, access);
|
||||||
body.emplace_back(ctx.dst->create<ast::CallStatement>(call));
|
body.emplace_back(ctx.dst->create<ast::CallStatement>(call));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func = ctx.dst->create<ast::Function>(
|
func = ctx.dst->create<ast::Function>(
|
||||||
ctx.dst->Sym(), params, ctx.dst->ty.void_(), ctx.dst->Block(body),
|
ctx.dst->Sym(), params, ctx.dst->ty.void_(),
|
||||||
ast::DecorationList{}, ast::DecorationList{});
|
ctx.dst->Block(body), ast::DecorationList{},
|
||||||
|
ast::DecorationList{});
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertGlobal(ctx, insert_after, func);
|
InsertGlobal(ctx, insert_after, func);
|
||||||
|
@ -667,12 +693,13 @@ struct DecomposeStorageAccess::State {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
DecomposeStorageAccess::Intrinsic::Intrinsic(ProgramID program_id,
|
DecomposeMemoryAccess::Intrinsic::Intrinsic(ProgramID program_id,
|
||||||
Op o,
|
Op o,
|
||||||
|
ast::StorageClass sc,
|
||||||
DataType ty)
|
DataType ty)
|
||||||
: Base(program_id), op(o), type(ty) {}
|
: Base(program_id), op(o), storage_class(sc), type(ty) {}
|
||||||
DecomposeStorageAccess::Intrinsic::~Intrinsic() = default;
|
DecomposeMemoryAccess::Intrinsic::~Intrinsic() = default;
|
||||||
std::string DecomposeStorageAccess::Intrinsic::InternalName() const {
|
std::string DecomposeMemoryAccess::Intrinsic::InternalName() const {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Op::kLoad:
|
case Op::kLoad:
|
||||||
|
@ -712,6 +739,7 @@ std::string DecomposeStorageAccess::Intrinsic::InternalName() const {
|
||||||
ss << "intrinsic_atomic_compare_exchange_weak_";
|
ss << "intrinsic_atomic_compare_exchange_weak_";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ss << storage_class << "_";
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DataType::kU32:
|
case DataType::kU32:
|
||||||
ss << "u32";
|
ss << "u32";
|
||||||
|
@ -753,16 +781,16 @@ std::string DecomposeStorageAccess::Intrinsic::InternalName() const {
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
DecomposeStorageAccess::Intrinsic* DecomposeStorageAccess::Intrinsic::Clone(
|
DecomposeMemoryAccess::Intrinsic* DecomposeMemoryAccess::Intrinsic::Clone(
|
||||||
CloneContext* ctx) const {
|
CloneContext* ctx) const {
|
||||||
return ctx->dst->ASTNodes().Create<DecomposeStorageAccess::Intrinsic>(
|
return ctx->dst->ASTNodes().Create<DecomposeMemoryAccess::Intrinsic>(
|
||||||
ctx->dst->ID(), op, type);
|
ctx->dst->ID(), op, storage_class, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
DecomposeStorageAccess::DecomposeStorageAccess() = default;
|
DecomposeMemoryAccess::DecomposeMemoryAccess() = default;
|
||||||
DecomposeStorageAccess::~DecomposeStorageAccess() = default;
|
DecomposeMemoryAccess::~DecomposeMemoryAccess() = default;
|
||||||
|
|
||||||
Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
Output DecomposeMemoryAccess::Run(const Program* in, const DataMap&) {
|
||||||
ProgramBuilder out;
|
ProgramBuilder out;
|
||||||
CloneContext ctx(&out, in);
|
CloneContext ctx(&out, in);
|
||||||
|
|
||||||
|
@ -770,9 +798,10 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||||
|
|
||||||
State state;
|
State state;
|
||||||
|
|
||||||
// Scan the AST nodes for storage buffer accesses. Complex expression chains
|
// Scan the AST nodes for storage and uniform buffer accesses. Complex
|
||||||
// (e.g. `storage_buffer.foo.bar[20].x`) are handled by maintaining an offset
|
// expression chains (e.g. `storage_buffer.foo.bar[20].x`) are handled by
|
||||||
// chain via the `state.TakeAccess()`, `state.AddAccess()` methods.
|
// maintaining an offset chain via the `state.TakeAccess()`,
|
||||||
|
// `state.AddAccess()` methods.
|
||||||
//
|
//
|
||||||
// Inner-most expression nodes are guaranteed to be visited first because AST
|
// Inner-most expression nodes are guaranteed to be visited first because AST
|
||||||
// nodes are fully immutable and require their children to be constructed
|
// nodes are fully immutable and require their children to be constructed
|
||||||
|
@ -781,8 +810,9 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||||
if (auto* ident = node->As<ast::IdentifierExpression>()) {
|
if (auto* ident = node->As<ast::IdentifierExpression>()) {
|
||||||
// X
|
// X
|
||||||
if (auto* var = sem.Get<sem::VariableUser>(ident)) {
|
if (auto* var = sem.Get<sem::VariableUser>(ident)) {
|
||||||
if (var->Variable()->StorageClass() == ast::StorageClass::kStorage) {
|
if (var->Variable()->StorageClass() == ast::StorageClass::kStorage ||
|
||||||
// Variable to a storage buffer
|
var->Variable()->StorageClass() == ast::StorageClass::kUniform) {
|
||||||
|
// Variable to a storage or uniform buffer
|
||||||
state.AddAccess(ident, {
|
state.AddAccess(ident, {
|
||||||
var,
|
var,
|
||||||
ToOffset(0u),
|
ToOffset(0u),
|
||||||
|
@ -940,7 +970,7 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
|
||||||
ctx.Replace(expr, load);
|
ctx.Replace(expr, load);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And replace all storage buffer assignments with stores
|
// And replace all storage and uniform buffer assignments with stores
|
||||||
for (auto& store : state.stores) {
|
for (auto& store : state.stores) {
|
||||||
auto* buf = store.target.var->Declaration();
|
auto* buf = store.target.var->Declaration();
|
||||||
auto* offset = store.target.offset->Build(ctx);
|
auto* offset = store.target.offset->Build(ctx);
|
|
@ -12,8 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#ifndef SRC_TRANSFORM_DECOMPOSE_STORAGE_ACCESS_H_
|
#ifndef SRC_TRANSFORM_DECOMPOSE_MEMORY_ACCESS_H_
|
||||||
#define SRC_TRANSFORM_DECOMPOSE_STORAGE_ACCESS_H_
|
#define SRC_TRANSFORM_DECOMPOSE_MEMORY_ACCESS_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -27,10 +27,10 @@ class CloneContext;
|
||||||
|
|
||||||
namespace transform {
|
namespace transform {
|
||||||
|
|
||||||
/// DecomposeStorageAccess is a transform used to replace storage buffer
|
/// DecomposeMemoryAccess is a transform used to replace storage and uniform
|
||||||
/// accesses with a combination of load, store or atomic functions on primitive
|
/// buffer accesses with a combination of load, store or atomic functions on
|
||||||
/// types.
|
/// primitive types.
|
||||||
class DecomposeStorageAccess : public Transform {
|
class DecomposeMemoryAccess : public Transform {
|
||||||
public:
|
public:
|
||||||
/// Intrinsic is an InternalDecoration that's used to decorate a stub function
|
/// Intrinsic is an InternalDecoration that's used to decorate a stub function
|
||||||
/// so that the HLSL transforms this into calls to
|
/// so that the HLSL transforms this into calls to
|
||||||
|
@ -73,8 +73,9 @@ class DecomposeStorageAccess : public Transform {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param program_id the identifier of the program that owns this node
|
/// @param program_id the identifier of the program that owns this node
|
||||||
/// @param o the op of the intrinsic
|
/// @param o the op of the intrinsic
|
||||||
|
/// @param sc the storage class of the buffer
|
||||||
/// @param ty the data type of the intrinsic
|
/// @param ty the data type of the intrinsic
|
||||||
Intrinsic(ProgramID program_id, Op o, DataType ty);
|
Intrinsic(ProgramID program_id, Op o, ast::StorageClass sc, DataType ty);
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~Intrinsic() override;
|
~Intrinsic() override;
|
||||||
|
|
||||||
|
@ -90,14 +91,17 @@ class DecomposeStorageAccess : public Transform {
|
||||||
/// The op of the intrinsic
|
/// The op of the intrinsic
|
||||||
Op const op;
|
Op const op;
|
||||||
|
|
||||||
|
/// The storage class of the buffer this intrinsic operates on
|
||||||
|
ast::StorageClass const storage_class;
|
||||||
|
|
||||||
/// The type of the intrinsic
|
/// The type of the intrinsic
|
||||||
DataType const type;
|
DataType const type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
DecomposeStorageAccess();
|
DecomposeMemoryAccess();
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~DecomposeStorageAccess() override;
|
~DecomposeMemoryAccess() override;
|
||||||
|
|
||||||
/// Runs the transform on `program`, returning the transformation result.
|
/// Runs the transform on `program`, returning the transformation result.
|
||||||
/// @param program the source program to transform
|
/// @param program the source program to transform
|
||||||
|
@ -111,4 +115,4 @@ class DecomposeStorageAccess : public Transform {
|
||||||
} // namespace transform
|
} // namespace transform
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
||||||
#endif // SRC_TRANSFORM_DECOMPOSE_STORAGE_ACCESS_H_
|
#endif // SRC_TRANSFORM_DECOMPOSE_MEMORY_ACCESS_H_
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "src/transform/decompose_storage_access.h"
|
#include "src/transform/decompose_memory_access.h"
|
||||||
|
|
||||||
#include "src/transform/test_helper.h"
|
#include "src/transform/test_helper.h"
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ namespace tint {
|
||||||
namespace transform {
|
namespace transform {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using DecomposeStorageAccessTest = TransformTest;
|
using DecomposeMemoryAccessTest = TransformTest;
|
||||||
|
|
||||||
TEST_F(DecomposeStorageAccessTest, BasicLoad) {
|
TEST_F(DecomposeMemoryAccessTest, SB_BasicLoad) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
[[block]]
|
[[block]]
|
||||||
struct SB {
|
struct SB {
|
||||||
|
@ -106,40 +106,40 @@ struct SB {
|
||||||
v : array<vec3<f32>, 2>;
|
v : array<vec3<f32>, 2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[internal(intrinsic_load_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol(buffer : SB, offset : u32) -> i32
|
fn tint_symbol(buffer : SB, offset : u32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_load_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_1(buffer : SB, offset : u32) -> u32
|
fn tint_symbol_1(buffer : SB, offset : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_load_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_2(buffer : SB, offset : u32) -> f32
|
fn tint_symbol_2(buffer : SB, offset : u32) -> f32
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec2_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec2_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_3(buffer : SB, offset : u32) -> vec2<i32>
|
fn tint_symbol_3(buffer : SB, offset : u32) -> vec2<i32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec2_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec2_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_4(buffer : SB, offset : u32) -> vec2<u32>
|
fn tint_symbol_4(buffer : SB, offset : u32) -> vec2<u32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec2_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec2_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_5(buffer : SB, offset : u32) -> vec2<f32>
|
fn tint_symbol_5(buffer : SB, offset : u32) -> vec2<f32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec3_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec3_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_6(buffer : SB, offset : u32) -> vec3<i32>
|
fn tint_symbol_6(buffer : SB, offset : u32) -> vec3<i32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec3_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec3_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_7(buffer : SB, offset : u32) -> vec3<u32>
|
fn tint_symbol_7(buffer : SB, offset : u32) -> vec3<u32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec3_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec3_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_8(buffer : SB, offset : u32) -> vec3<f32>
|
fn tint_symbol_8(buffer : SB, offset : u32) -> vec3<f32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec4_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec4_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_9(buffer : SB, offset : u32) -> vec4<i32>
|
fn tint_symbol_9(buffer : SB, offset : u32) -> vec4<i32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec4_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec4_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_10(buffer : SB, offset : u32) -> vec4<u32>
|
fn tint_symbol_10(buffer : SB, offset : u32) -> vec4<u32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec4_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec4_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_11(buffer : SB, offset : u32) -> vec4<f32>
|
fn tint_symbol_11(buffer : SB, offset : u32) -> vec4<f32>
|
||||||
|
|
||||||
fn tint_symbol_12(buffer : SB, offset : u32) -> mat2x2<f32> {
|
fn tint_symbol_12(buffer : SB, offset : u32) -> mat2x2<f32> {
|
||||||
|
@ -211,12 +211,206 @@ fn main() {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto got = Run<DecomposeStorageAccess>(src);
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DecomposeStorageAccessTest, BasicStore) {
|
TEST_F(DecomposeMemoryAccessTest, UB_BasicLoad) {
|
||||||
|
auto* src = R"(
|
||||||
|
[[block]]
|
||||||
|
struct UB {
|
||||||
|
a : i32;
|
||||||
|
b : u32;
|
||||||
|
c : f32;
|
||||||
|
d : vec2<i32>;
|
||||||
|
e : vec2<u32>;
|
||||||
|
f : vec2<f32>;
|
||||||
|
g : vec3<i32>;
|
||||||
|
h : vec3<u32>;
|
||||||
|
i : vec3<f32>;
|
||||||
|
j : vec4<i32>;
|
||||||
|
k : vec4<u32>;
|
||||||
|
l : vec4<f32>;
|
||||||
|
m : mat2x2<f32>;
|
||||||
|
n : mat2x3<f32>;
|
||||||
|
o : mat2x4<f32>;
|
||||||
|
p : mat3x2<f32>;
|
||||||
|
q : mat3x3<f32>;
|
||||||
|
r : mat3x4<f32>;
|
||||||
|
s : mat4x2<f32>;
|
||||||
|
t : mat4x3<f32>;
|
||||||
|
u : mat4x4<f32>;
|
||||||
|
v : array<vec3<f32>, 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[group(0), binding(0)]] var<uniform> ub : UB;
|
||||||
|
|
||||||
|
[[stage(compute)]]
|
||||||
|
fn main() {
|
||||||
|
var a : i32 = ub.a;
|
||||||
|
var b : u32 = ub.b;
|
||||||
|
var c : f32 = ub.c;
|
||||||
|
var d : vec2<i32> = ub.d;
|
||||||
|
var e : vec2<u32> = ub.e;
|
||||||
|
var f : vec2<f32> = ub.f;
|
||||||
|
var g : vec3<i32> = ub.g;
|
||||||
|
var h : vec3<u32> = ub.h;
|
||||||
|
var i : vec3<f32> = ub.i;
|
||||||
|
var j : vec4<i32> = ub.j;
|
||||||
|
var k : vec4<u32> = ub.k;
|
||||||
|
var l : vec4<f32> = ub.l;
|
||||||
|
var m : mat2x2<f32> = ub.m;
|
||||||
|
var n : mat2x3<f32> = ub.n;
|
||||||
|
var o : mat2x4<f32> = ub.o;
|
||||||
|
var p : mat3x2<f32> = ub.p;
|
||||||
|
var q : mat3x3<f32> = ub.q;
|
||||||
|
var r : mat3x4<f32> = ub.r;
|
||||||
|
var s : mat4x2<f32> = ub.s;
|
||||||
|
var t : mat4x3<f32> = ub.t;
|
||||||
|
var u : mat4x4<f32> = ub.u;
|
||||||
|
var v : array<vec3<f32>, 2> = ub.v;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto* expect = R"(
|
||||||
|
[[block]]
|
||||||
|
struct UB {
|
||||||
|
a : i32;
|
||||||
|
b : u32;
|
||||||
|
c : f32;
|
||||||
|
d : vec2<i32>;
|
||||||
|
e : vec2<u32>;
|
||||||
|
f : vec2<f32>;
|
||||||
|
g : vec3<i32>;
|
||||||
|
h : vec3<u32>;
|
||||||
|
i : vec3<f32>;
|
||||||
|
j : vec4<i32>;
|
||||||
|
k : vec4<u32>;
|
||||||
|
l : vec4<f32>;
|
||||||
|
m : mat2x2<f32>;
|
||||||
|
n : mat2x3<f32>;
|
||||||
|
o : mat2x4<f32>;
|
||||||
|
p : mat3x2<f32>;
|
||||||
|
q : mat3x3<f32>;
|
||||||
|
r : mat3x4<f32>;
|
||||||
|
s : mat4x2<f32>;
|
||||||
|
t : mat4x3<f32>;
|
||||||
|
u : mat4x4<f32>;
|
||||||
|
v : array<vec3<f32>, 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol(buffer : UB, offset : u32) -> i32
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_1(buffer : UB, offset : u32) -> u32
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_2(buffer : UB, offset : u32) -> f32
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_vec2_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_3(buffer : UB, offset : u32) -> vec2<i32>
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_vec2_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_4(buffer : UB, offset : u32) -> vec2<u32>
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_vec2_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_5(buffer : UB, offset : u32) -> vec2<f32>
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_vec3_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_6(buffer : UB, offset : u32) -> vec3<i32>
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_vec3_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_7(buffer : UB, offset : u32) -> vec3<u32>
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_vec3_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_8(buffer : UB, offset : u32) -> vec3<f32>
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_vec4_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_9(buffer : UB, offset : u32) -> vec4<i32>
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_vec4_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_10(buffer : UB, offset : u32) -> vec4<u32>
|
||||||
|
|
||||||
|
[[internal(intrinsic_load_uniform_vec4_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
|
fn tint_symbol_11(buffer : UB, offset : u32) -> vec4<f32>
|
||||||
|
|
||||||
|
fn tint_symbol_12(buffer : UB, offset : u32) -> mat2x2<f32> {
|
||||||
|
return mat2x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tint_symbol_13(buffer : UB, offset : u32) -> mat2x3<f32> {
|
||||||
|
return mat2x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tint_symbol_14(buffer : UB, offset : u32) -> mat2x4<f32> {
|
||||||
|
return mat2x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tint_symbol_15(buffer : UB, offset : u32) -> mat3x2<f32> {
|
||||||
|
return mat3x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tint_symbol_16(buffer : UB, offset : u32) -> mat3x3<f32> {
|
||||||
|
return mat3x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tint_symbol_17(buffer : UB, offset : u32) -> mat3x4<f32> {
|
||||||
|
return mat3x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tint_symbol_18(buffer : UB, offset : u32) -> mat4x2<f32> {
|
||||||
|
return mat4x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tint_symbol_19(buffer : UB, offset : u32) -> mat4x3<f32> {
|
||||||
|
return mat4x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)), tint_symbol_8(buffer, (offset + 48u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tint_symbol_20(buffer : UB, offset : u32) -> mat4x4<f32> {
|
||||||
|
return mat4x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)), tint_symbol_11(buffer, (offset + 48u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tint_symbol_21(buffer : UB, offset : u32) -> array<vec3<f32>, 2> {
|
||||||
|
return array<vec3<f32>, 2>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[group(0), binding(0)]] var<uniform> ub : UB;
|
||||||
|
|
||||||
|
[[stage(compute)]]
|
||||||
|
fn main() {
|
||||||
|
var a : i32 = tint_symbol(ub, 0u);
|
||||||
|
var b : u32 = tint_symbol_1(ub, 4u);
|
||||||
|
var c : f32 = tint_symbol_2(ub, 8u);
|
||||||
|
var d : vec2<i32> = tint_symbol_3(ub, 16u);
|
||||||
|
var e : vec2<u32> = tint_symbol_4(ub, 24u);
|
||||||
|
var f : vec2<f32> = tint_symbol_5(ub, 32u);
|
||||||
|
var g : vec3<i32> = tint_symbol_6(ub, 48u);
|
||||||
|
var h : vec3<u32> = tint_symbol_7(ub, 64u);
|
||||||
|
var i : vec3<f32> = tint_symbol_8(ub, 80u);
|
||||||
|
var j : vec4<i32> = tint_symbol_9(ub, 96u);
|
||||||
|
var k : vec4<u32> = tint_symbol_10(ub, 112u);
|
||||||
|
var l : vec4<f32> = tint_symbol_11(ub, 128u);
|
||||||
|
var m : mat2x2<f32> = tint_symbol_12(ub, 144u);
|
||||||
|
var n : mat2x3<f32> = tint_symbol_13(ub, 160u);
|
||||||
|
var o : mat2x4<f32> = tint_symbol_14(ub, 192u);
|
||||||
|
var p : mat3x2<f32> = tint_symbol_15(ub, 224u);
|
||||||
|
var q : mat3x3<f32> = tint_symbol_16(ub, 256u);
|
||||||
|
var r : mat3x4<f32> = tint_symbol_17(ub, 304u);
|
||||||
|
var s : mat4x2<f32> = tint_symbol_18(ub, 352u);
|
||||||
|
var t : mat4x3<f32> = tint_symbol_19(ub, 384u);
|
||||||
|
var u : mat4x4<f32> = tint_symbol_20(ub, 448u);
|
||||||
|
var v : array<vec3<f32>, 2> = tint_symbol_21(ub, 512u);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
|
EXPECT_EQ(expect, str(got));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DecomposeMemoryAccessTest, SB_BasicStore) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
[[block]]
|
[[block]]
|
||||||
struct SB {
|
struct SB {
|
||||||
|
@ -300,40 +494,40 @@ struct SB {
|
||||||
v : array<vec3<f32>, 2>;
|
v : array<vec3<f32>, 2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[internal(intrinsic_store_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol(buffer : SB, offset : u32, value : i32)
|
fn tint_symbol(buffer : SB, offset : u32, value : i32)
|
||||||
|
|
||||||
[[internal(intrinsic_store_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_1(buffer : SB, offset : u32, value : u32)
|
fn tint_symbol_1(buffer : SB, offset : u32, value : u32)
|
||||||
|
|
||||||
[[internal(intrinsic_store_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_2(buffer : SB, offset : u32, value : f32)
|
fn tint_symbol_2(buffer : SB, offset : u32, value : f32)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec2_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec2_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_3(buffer : SB, offset : u32, value : vec2<i32>)
|
fn tint_symbol_3(buffer : SB, offset : u32, value : vec2<i32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec2_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec2_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_4(buffer : SB, offset : u32, value : vec2<u32>)
|
fn tint_symbol_4(buffer : SB, offset : u32, value : vec2<u32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec2_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec2_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_5(buffer : SB, offset : u32, value : vec2<f32>)
|
fn tint_symbol_5(buffer : SB, offset : u32, value : vec2<f32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec3_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec3_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_6(buffer : SB, offset : u32, value : vec3<i32>)
|
fn tint_symbol_6(buffer : SB, offset : u32, value : vec3<i32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec3_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec3_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_7(buffer : SB, offset : u32, value : vec3<u32>)
|
fn tint_symbol_7(buffer : SB, offset : u32, value : vec3<u32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec3_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec3_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_8(buffer : SB, offset : u32, value : vec3<f32>)
|
fn tint_symbol_8(buffer : SB, offset : u32, value : vec3<f32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec4_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec4_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_9(buffer : SB, offset : u32, value : vec4<i32>)
|
fn tint_symbol_9(buffer : SB, offset : u32, value : vec4<i32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec4_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec4_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_10(buffer : SB, offset : u32, value : vec4<u32>)
|
fn tint_symbol_10(buffer : SB, offset : u32, value : vec4<u32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec4_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec4_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_11(buffer : SB, offset : u32, value : vec4<f32>)
|
fn tint_symbol_11(buffer : SB, offset : u32, value : vec4<f32>)
|
||||||
|
|
||||||
fn tint_symbol_12(buffer : SB, offset : u32, value : mat2x2<f32>) {
|
fn tint_symbol_12(buffer : SB, offset : u32, value : mat2x2<f32>) {
|
||||||
|
@ -424,12 +618,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto got = Run<DecomposeStorageAccess>(src);
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DecomposeStorageAccessTest, LoadStructure) {
|
TEST_F(DecomposeMemoryAccessTest, LoadStructure) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
[[block]]
|
[[block]]
|
||||||
struct SB {
|
struct SB {
|
||||||
|
@ -492,40 +686,40 @@ struct SB {
|
||||||
v : array<vec3<f32>, 2>;
|
v : array<vec3<f32>, 2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[internal(intrinsic_load_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol(buffer : SB, offset : u32) -> i32
|
fn tint_symbol(buffer : SB, offset : u32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_load_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_1(buffer : SB, offset : u32) -> u32
|
fn tint_symbol_1(buffer : SB, offset : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_load_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_2(buffer : SB, offset : u32) -> f32
|
fn tint_symbol_2(buffer : SB, offset : u32) -> f32
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec2_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec2_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_3(buffer : SB, offset : u32) -> vec2<i32>
|
fn tint_symbol_3(buffer : SB, offset : u32) -> vec2<i32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec2_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec2_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_4(buffer : SB, offset : u32) -> vec2<u32>
|
fn tint_symbol_4(buffer : SB, offset : u32) -> vec2<u32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec2_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec2_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_5(buffer : SB, offset : u32) -> vec2<f32>
|
fn tint_symbol_5(buffer : SB, offset : u32) -> vec2<f32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec3_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec3_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_6(buffer : SB, offset : u32) -> vec3<i32>
|
fn tint_symbol_6(buffer : SB, offset : u32) -> vec3<i32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec3_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec3_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_7(buffer : SB, offset : u32) -> vec3<u32>
|
fn tint_symbol_7(buffer : SB, offset : u32) -> vec3<u32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec3_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec3_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_8(buffer : SB, offset : u32) -> vec3<f32>
|
fn tint_symbol_8(buffer : SB, offset : u32) -> vec3<f32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec4_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec4_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_9(buffer : SB, offset : u32) -> vec4<i32>
|
fn tint_symbol_9(buffer : SB, offset : u32) -> vec4<i32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec4_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec4_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_10(buffer : SB, offset : u32) -> vec4<u32>
|
fn tint_symbol_10(buffer : SB, offset : u32) -> vec4<u32>
|
||||||
|
|
||||||
[[internal(intrinsic_load_vec4_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_vec4_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_11(buffer : SB, offset : u32) -> vec4<f32>
|
fn tint_symbol_11(buffer : SB, offset : u32) -> vec4<f32>
|
||||||
|
|
||||||
fn tint_symbol_12(buffer : SB, offset : u32) -> mat2x2<f32> {
|
fn tint_symbol_12(buffer : SB, offset : u32) -> mat2x2<f32> {
|
||||||
|
@ -580,12 +774,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto got = Run<DecomposeStorageAccess>(src);
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DecomposeStorageAccessTest, StoreStructure) {
|
TEST_F(DecomposeMemoryAccessTest, StoreStructure) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
[[block]]
|
[[block]]
|
||||||
struct SB {
|
struct SB {
|
||||||
|
@ -648,40 +842,40 @@ struct SB {
|
||||||
v : array<vec3<f32>, 2>;
|
v : array<vec3<f32>, 2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[internal(intrinsic_store_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol(buffer : SB, offset : u32, value : i32)
|
fn tint_symbol(buffer : SB, offset : u32, value : i32)
|
||||||
|
|
||||||
[[internal(intrinsic_store_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_1(buffer : SB, offset : u32, value : u32)
|
fn tint_symbol_1(buffer : SB, offset : u32, value : u32)
|
||||||
|
|
||||||
[[internal(intrinsic_store_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_2(buffer : SB, offset : u32, value : f32)
|
fn tint_symbol_2(buffer : SB, offset : u32, value : f32)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec2_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec2_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_3(buffer : SB, offset : u32, value : vec2<i32>)
|
fn tint_symbol_3(buffer : SB, offset : u32, value : vec2<i32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec2_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec2_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_4(buffer : SB, offset : u32, value : vec2<u32>)
|
fn tint_symbol_4(buffer : SB, offset : u32, value : vec2<u32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec2_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec2_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_5(buffer : SB, offset : u32, value : vec2<f32>)
|
fn tint_symbol_5(buffer : SB, offset : u32, value : vec2<f32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec3_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec3_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_6(buffer : SB, offset : u32, value : vec3<i32>)
|
fn tint_symbol_6(buffer : SB, offset : u32, value : vec3<i32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec3_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec3_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_7(buffer : SB, offset : u32, value : vec3<u32>)
|
fn tint_symbol_7(buffer : SB, offset : u32, value : vec3<u32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec3_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec3_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_8(buffer : SB, offset : u32, value : vec3<f32>)
|
fn tint_symbol_8(buffer : SB, offset : u32, value : vec3<f32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec4_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec4_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_9(buffer : SB, offset : u32, value : vec4<i32>)
|
fn tint_symbol_9(buffer : SB, offset : u32, value : vec4<i32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec4_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec4_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_10(buffer : SB, offset : u32, value : vec4<u32>)
|
fn tint_symbol_10(buffer : SB, offset : u32, value : vec4<u32>)
|
||||||
|
|
||||||
[[internal(intrinsic_store_vec4_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_store_storage_vec4_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_11(buffer : SB, offset : u32, value : vec4<f32>)
|
fn tint_symbol_11(buffer : SB, offset : u32, value : vec4<f32>)
|
||||||
|
|
||||||
fn tint_symbol_12(buffer : SB, offset : u32, value : mat2x2<f32>) {
|
fn tint_symbol_12(buffer : SB, offset : u32, value : mat2x2<f32>) {
|
||||||
|
@ -776,12 +970,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto got = Run<DecomposeStorageAccess>(src);
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DecomposeStorageAccessTest, ComplexStaticAccessChain) {
|
TEST_F(DecomposeMemoryAccessTest, ComplexStaticAccessChain) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
struct S1 {
|
struct S1 {
|
||||||
a : i32;
|
a : i32;
|
||||||
|
@ -837,7 +1031,7 @@ struct SB {
|
||||||
b : [[stride(256)]] array<S2>;
|
b : [[stride(256)]] array<S2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[internal(intrinsic_load_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol(buffer : SB, offset : u32) -> f32
|
fn tint_symbol(buffer : SB, offset : u32) -> f32
|
||||||
|
|
||||||
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
|
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
|
||||||
|
@ -848,12 +1042,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto got = Run<DecomposeStorageAccess>(src);
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DecomposeStorageAccessTest, ComplexDynamicAccessChain) {
|
TEST_F(DecomposeMemoryAccessTest, ComplexDynamicAccessChain) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
struct S1 {
|
struct S1 {
|
||||||
a : i32;
|
a : i32;
|
||||||
|
@ -905,7 +1099,7 @@ struct SB {
|
||||||
b : [[stride(256)]] array<S2>;
|
b : [[stride(256)]] array<S2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[internal(intrinsic_load_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol(buffer : SB, offset : u32) -> f32
|
fn tint_symbol(buffer : SB, offset : u32) -> f32
|
||||||
|
|
||||||
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
|
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
|
||||||
|
@ -919,12 +1113,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto got = Run<DecomposeStorageAccess>(src);
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DecomposeStorageAccessTest, ComplexDynamicAccessChainWithAliases) {
|
TEST_F(DecomposeMemoryAccessTest, ComplexDynamicAccessChainWithAliases) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
struct S1 {
|
struct S1 {
|
||||||
a : i32;
|
a : i32;
|
||||||
|
@ -992,7 +1186,7 @@ struct SB {
|
||||||
b : A2_Array;
|
b : A2_Array;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[internal(intrinsic_load_f32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol(buffer : SB, offset : u32) -> f32
|
fn tint_symbol(buffer : SB, offset : u32) -> f32
|
||||||
|
|
||||||
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
|
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
|
||||||
|
@ -1006,12 +1200,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto got = Run<DecomposeStorageAccess>(src);
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DecomposeStorageAccessTest, StorageBufferAtomics) {
|
TEST_F(DecomposeMemoryAccessTest, StorageBufferAtomics) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
[[block]]
|
[[block]]
|
||||||
struct SB {
|
struct SB {
|
||||||
|
@ -1056,64 +1250,64 @@ struct SB {
|
||||||
b : atomic<u32>;
|
b : atomic<u32>;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_store_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_store_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol(buffer : SB, offset : u32, param_1 : i32)
|
fn tint_symbol(buffer : SB, offset : u32, param_1 : i32)
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_load_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_load_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_1(buffer : SB, offset : u32) -> i32
|
fn tint_symbol_1(buffer : SB, offset : u32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_add_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_add_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_2(buffer : SB, offset : u32, param_1 : i32) -> i32
|
fn tint_symbol_2(buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_max_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_max_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_3(buffer : SB, offset : u32, param_1 : i32) -> i32
|
fn tint_symbol_3(buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_min_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_min_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_4(buffer : SB, offset : u32, param_1 : i32) -> i32
|
fn tint_symbol_4(buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_and_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_and_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_5(buffer : SB, offset : u32, param_1 : i32) -> i32
|
fn tint_symbol_5(buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_or_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_or_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_6(buffer : SB, offset : u32, param_1 : i32) -> i32
|
fn tint_symbol_6(buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_xor_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_xor_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_7(buffer : SB, offset : u32, param_1 : i32) -> i32
|
fn tint_symbol_7(buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_exchange_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_exchange_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_8(buffer : SB, offset : u32, param_1 : i32) -> i32
|
fn tint_symbol_8(buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_compare_exchange_weak_i32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_compare_exchange_weak_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_9(buffer : SB, offset : u32, param_1 : i32, param_2 : i32) -> vec2<i32>
|
fn tint_symbol_9(buffer : SB, offset : u32, param_1 : i32, param_2 : i32) -> vec2<i32>
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_store_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_store_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_10(buffer : SB, offset : u32, param_1 : u32)
|
fn tint_symbol_10(buffer : SB, offset : u32, param_1 : u32)
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_load_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_load_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_11(buffer : SB, offset : u32) -> u32
|
fn tint_symbol_11(buffer : SB, offset : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_add_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_add_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_12(buffer : SB, offset : u32, param_1 : u32) -> u32
|
fn tint_symbol_12(buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_max_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_max_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_13(buffer : SB, offset : u32, param_1 : u32) -> u32
|
fn tint_symbol_13(buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_min_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_min_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_14(buffer : SB, offset : u32, param_1 : u32) -> u32
|
fn tint_symbol_14(buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_and_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_and_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_15(buffer : SB, offset : u32, param_1 : u32) -> u32
|
fn tint_symbol_15(buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_or_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_or_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_16(buffer : SB, offset : u32, param_1 : u32) -> u32
|
fn tint_symbol_16(buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_xor_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_xor_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_17(buffer : SB, offset : u32, param_1 : u32) -> u32
|
fn tint_symbol_17(buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_exchange_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_exchange_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_18(buffer : SB, offset : u32, param_1 : u32) -> u32
|
fn tint_symbol_18(buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||||
|
|
||||||
[[internal(intrinsic_atomic_compare_exchange_weak_u32), internal(disable_validation__function_has_no_body)]]
|
[[internal(intrinsic_atomic_compare_exchange_weak_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||||
fn tint_symbol_19(buffer : SB, offset : u32, param_1 : u32, param_2 : u32) -> vec2<u32>
|
fn tint_symbol_19(buffer : SB, offset : u32, param_1 : u32, param_2 : u32) -> vec2<u32>
|
||||||
|
|
||||||
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
|
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
|
||||||
|
@ -1143,12 +1337,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto got = Run<DecomposeStorageAccess>(src);
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DecomposeStorageAccessTest, WorkgroupBufferAtomics) {
|
TEST_F(DecomposeMemoryAccessTest, WorkgroupBufferAtomics) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
struct S {
|
struct S {
|
||||||
padding : vec4<f32>;
|
padding : vec4<f32>;
|
||||||
|
@ -1185,7 +1379,7 @@ fn main() {
|
||||||
|
|
||||||
auto* expect = src;
|
auto* expect = src;
|
||||||
|
|
||||||
auto got = Run<DecomposeStorageAccess>(src);
|
auto got = Run<DecomposeMemoryAccess>(src);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@
|
||||||
#include "src/program_builder.h"
|
#include "src/program_builder.h"
|
||||||
#include "src/transform/calculate_array_length.h"
|
#include "src/transform/calculate_array_length.h"
|
||||||
#include "src/transform/canonicalize_entry_point_io.h"
|
#include "src/transform/canonicalize_entry_point_io.h"
|
||||||
#include "src/transform/decompose_storage_access.h"
|
#include "src/transform/decompose_memory_access.h"
|
||||||
#include "src/transform/external_texture_transform.h"
|
#include "src/transform/external_texture_transform.h"
|
||||||
#include "src/transform/inline_pointer_lets.h"
|
#include "src/transform/inline_pointer_lets.h"
|
||||||
#include "src/transform/manager.h"
|
#include "src/transform/manager.h"
|
||||||
|
@ -41,13 +41,13 @@ Output Hlsl::Run(const Program* in, const DataMap&) {
|
||||||
manager.Add<InlinePointerLets>();
|
manager.Add<InlinePointerLets>();
|
||||||
// Simplify cleans up messy `*(&(expr))` expressions from InlinePointerLets.
|
// Simplify cleans up messy `*(&(expr))` expressions from InlinePointerLets.
|
||||||
manager.Add<Simplify>();
|
manager.Add<Simplify>();
|
||||||
// DecomposeStorageAccess must come after InlinePointerLets as we cannot take
|
// DecomposeMemoryAccess must come after InlinePointerLets as we cannot take
|
||||||
// the address of calls to DecomposeStorageAccess::Intrinsic. Must also come
|
// the address of calls to DecomposeMemoryAccess::Intrinsic. Must also come
|
||||||
// after Simplify, as we need to fold away the address-of and defers of
|
// after Simplify, as we need to fold away the address-of and defers of
|
||||||
// `*(&(intrinsic_load()))` expressions.
|
// `*(&(intrinsic_load()))` expressions.
|
||||||
manager.Add<DecomposeStorageAccess>();
|
manager.Add<DecomposeMemoryAccess>();
|
||||||
// CalculateArrayLength must come after DecomposeStorageAccess, as
|
// CalculateArrayLength must come after DecomposeMemoryAccess, as
|
||||||
// DecomposeStorageAccess special-cases the arrayLength() intrinsic, which
|
// DecomposeMemoryAccess special-cases the arrayLength() intrinsic, which
|
||||||
// will be transformed by CalculateArrayLength
|
// will be transformed by CalculateArrayLength
|
||||||
manager.Add<CalculateArrayLength>();
|
manager.Add<CalculateArrayLength>();
|
||||||
manager.Add<ExternalTextureTransform>();
|
manager.Add<ExternalTextureTransform>();
|
||||||
|
|
|
@ -429,9 +429,19 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto* intrinsic =
|
if (auto* intrinsic =
|
||||||
ast::GetDecoration<transform::DecomposeStorageAccess::Intrinsic>(
|
ast::GetDecoration<transform::DecomposeMemoryAccess::Intrinsic>(
|
||||||
func->Declaration()->decorations())) {
|
func->Declaration()->decorations())) {
|
||||||
return EmitDecomposeStorageAccessIntrinsic(pre, out, expr, intrinsic);
|
switch (intrinsic->storage_class) {
|
||||||
|
case ast::StorageClass::kUniform:
|
||||||
|
return EmitUniformBufferAccess(pre, out, expr, intrinsic);
|
||||||
|
case ast::StorageClass::kStorage:
|
||||||
|
return EmitStorageBufferAccess(pre, out, expr, intrinsic);
|
||||||
|
default:
|
||||||
|
TINT_UNREACHABLE(diagnostics_)
|
||||||
|
<< "unsupported DecomposeMemoryAccess::Intrinsic storage class:"
|
||||||
|
<< intrinsic->storage_class;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,15 +517,122 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitDecomposeStorageAccessIntrinsic(
|
bool GeneratorImpl::EmitUniformBufferAccess(
|
||||||
std::ostream& pre,
|
std::ostream& pre,
|
||||||
std::ostream& out,
|
std::ostream& out,
|
||||||
ast::CallExpression* expr,
|
ast::CallExpression* expr,
|
||||||
const transform::DecomposeStorageAccess::Intrinsic* intrinsic) {
|
const transform::DecomposeMemoryAccess::Intrinsic* intrinsic) {
|
||||||
const auto& params = expr->params();
|
const auto& params = expr->params();
|
||||||
|
|
||||||
using Op = transform::DecomposeStorageAccess::Intrinsic::Op;
|
std::string scalar_offset = generate_name("scalar_offset");
|
||||||
using DataType = transform::DecomposeStorageAccess::Intrinsic::DataType;
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "const int " << scalar_offset << " = (";
|
||||||
|
if (!EmitExpression(pre, ss, params[1])) { // offset
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
make_indent(ss << ") / 4;" << std::endl);
|
||||||
|
pre << ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
using Op = transform::DecomposeMemoryAccess::Intrinsic::Op;
|
||||||
|
using DataType = transform::DecomposeMemoryAccess::Intrinsic::DataType;
|
||||||
|
switch (intrinsic->op) {
|
||||||
|
case Op::kLoad: {
|
||||||
|
auto cast = [&](const char* to, auto&& load) {
|
||||||
|
out << to << "(";
|
||||||
|
auto result = load();
|
||||||
|
out << ")";
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
auto load_scalar = [&]() {
|
||||||
|
if (!EmitExpression(pre, out, params[0])) { // buffer
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out << "[" << scalar_offset << " / 4][" << scalar_offset << " % 4]";
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
// Has a minimum alignment of 8 bytes, so is either .xy or .zw
|
||||||
|
auto load_vec2 = [&] {
|
||||||
|
std::string ubo_load = generate_name("ubo_load");
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "uint4 " << ubo_load << " = ";
|
||||||
|
if (!EmitExpression(pre, ss, params[0])) { // buffer
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ss << "[" << scalar_offset << " / 4]";
|
||||||
|
make_indent(ss << ";" << std::endl);
|
||||||
|
pre << ss.str();
|
||||||
|
|
||||||
|
out << "(" << scalar_offset << " & 2) ? " << ubo_load
|
||||||
|
<< ".zw : " << ubo_load << ".xy";
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
// vec3 has a minimum alignment of 16 bytes, so is just a .xyz swizzle
|
||||||
|
auto load_vec3 = [&] {
|
||||||
|
if (!EmitExpression(pre, out, params[0])) { // buffer
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out << "[" << scalar_offset << " / 4].xyz";
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
// vec4 has a minimum alignment of 16 bytes, easiest case
|
||||||
|
auto load_vec4 = [&] {
|
||||||
|
if (!EmitExpression(pre, out, params[0])) { // buffer
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out << "[" << scalar_offset << " / 4]";
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
switch (intrinsic->type) {
|
||||||
|
case DataType::kU32:
|
||||||
|
return load_scalar();
|
||||||
|
case DataType::kF32:
|
||||||
|
return cast("asfloat", load_scalar);
|
||||||
|
case DataType::kI32:
|
||||||
|
return cast("asint", load_scalar);
|
||||||
|
case DataType::kVec2U32:
|
||||||
|
return load_vec2();
|
||||||
|
case DataType::kVec2F32:
|
||||||
|
return cast("asfloat", load_vec2);
|
||||||
|
case DataType::kVec2I32:
|
||||||
|
return cast("asint", load_vec2);
|
||||||
|
case DataType::kVec3U32:
|
||||||
|
return load_vec3();
|
||||||
|
case DataType::kVec3F32:
|
||||||
|
return cast("asfloat", load_vec3);
|
||||||
|
case DataType::kVec3I32:
|
||||||
|
return cast("asint", load_vec3);
|
||||||
|
case DataType::kVec4U32:
|
||||||
|
return load_vec4();
|
||||||
|
case DataType::kVec4F32:
|
||||||
|
return cast("asfloat", load_vec4);
|
||||||
|
case DataType::kVec4I32:
|
||||||
|
return cast("asint", load_vec4);
|
||||||
|
}
|
||||||
|
TINT_UNREACHABLE(diagnostics_)
|
||||||
|
<< "unsupported DecomposeMemoryAccess::Intrinsic::DataType: "
|
||||||
|
<< static_cast<int>(intrinsic->type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TINT_UNREACHABLE(diagnostics_)
|
||||||
|
<< "unsupported DecomposeMemoryAccess::Intrinsic::Op: "
|
||||||
|
<< static_cast<int>(intrinsic->op);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeneratorImpl::EmitStorageBufferAccess(
|
||||||
|
std::ostream& pre,
|
||||||
|
std::ostream& out,
|
||||||
|
ast::CallExpression* expr,
|
||||||
|
const transform::DecomposeMemoryAccess::Intrinsic* intrinsic) {
|
||||||
|
const auto& params = expr->params();
|
||||||
|
|
||||||
|
using Op = transform::DecomposeMemoryAccess::Intrinsic::Op;
|
||||||
|
using DataType = transform::DecomposeMemoryAccess::Intrinsic::DataType;
|
||||||
switch (intrinsic->op) {
|
switch (intrinsic->op) {
|
||||||
case Op::kLoad: {
|
case Op::kLoad: {
|
||||||
auto load = [&](const char* cast, int n) {
|
auto load = [&](const char* cast, int n) {
|
||||||
|
@ -565,7 +682,7 @@ bool GeneratorImpl::EmitDecomposeStorageAccessIntrinsic(
|
||||||
return load("asint", 4);
|
return load("asint", 4);
|
||||||
}
|
}
|
||||||
TINT_UNREACHABLE(diagnostics_)
|
TINT_UNREACHABLE(diagnostics_)
|
||||||
<< "unsupported DecomposeStorageAccess::Intrinsic::DataType: "
|
<< "unsupported DecomposeMemoryAccess::Intrinsic::DataType: "
|
||||||
<< static_cast<int>(intrinsic->type);
|
<< static_cast<int>(intrinsic->type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -617,7 +734,7 @@ bool GeneratorImpl::EmitDecomposeStorageAccessIntrinsic(
|
||||||
return store(4);
|
return store(4);
|
||||||
}
|
}
|
||||||
TINT_UNREACHABLE(diagnostics_)
|
TINT_UNREACHABLE(diagnostics_)
|
||||||
<< "unsupported DecomposeStorageAccess::Intrinsic::DataType: "
|
<< "unsupported DecomposeMemoryAccess::Intrinsic::DataType: "
|
||||||
<< static_cast<int>(intrinsic->type);
|
<< static_cast<int>(intrinsic->type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -636,7 +753,7 @@ bool GeneratorImpl::EmitDecomposeStorageAccessIntrinsic(
|
||||||
}
|
}
|
||||||
|
|
||||||
TINT_UNREACHABLE(diagnostics_)
|
TINT_UNREACHABLE(diagnostics_)
|
||||||
<< "unsupported DecomposeStorageAccess::Intrinsic::Op: "
|
<< "unsupported DecomposeMemoryAccess::Intrinsic::Op: "
|
||||||
<< static_cast<int>(intrinsic->op);
|
<< static_cast<int>(intrinsic->op);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -645,19 +762,19 @@ bool GeneratorImpl::EmitStorageAtomicCall(
|
||||||
std::ostream& pre,
|
std::ostream& pre,
|
||||||
std::ostream& out,
|
std::ostream& out,
|
||||||
ast::CallExpression* expr,
|
ast::CallExpression* expr,
|
||||||
transform::DecomposeStorageAccess::Intrinsic::Op op) {
|
transform::DecomposeMemoryAccess::Intrinsic::Op op) {
|
||||||
using Op = transform::DecomposeStorageAccess::Intrinsic::Op;
|
using Op = transform::DecomposeMemoryAccess::Intrinsic::Op;
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
std::string result = generate_name("atomic_result");
|
std::string result = generate_name("atomic_result");
|
||||||
|
|
||||||
auto* result_ty = TypeOf(expr);
|
auto* result_ty = TypeOf(expr);
|
||||||
if (!result_ty->Is<sem::Void>()) {
|
if (!result_ty->Is<sem::Void>()) {
|
||||||
if (!EmitType(ss, TypeOf(expr), ast::StorageClass::kNone,
|
if (!EmitTypeAndName(ss, TypeOf(expr), ast::StorageClass::kNone,
|
||||||
ast::Access::kUndefined, "")) {
|
ast::Access::kUndefined, result)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ss << " " << result << " = ";
|
ss << " = ";
|
||||||
if (!EmitZeroValue(ss, result_ty)) {
|
if (!EmitZeroValue(ss, result_ty)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -693,11 +810,11 @@ bool GeneratorImpl::EmitStorageAtomicCall(
|
||||||
// InterlockedExchange and discard the returned value
|
// InterlockedExchange and discard the returned value
|
||||||
auto* value = expr->params()[2];
|
auto* value = expr->params()[2];
|
||||||
auto* value_ty = TypeOf(value);
|
auto* value_ty = TypeOf(value);
|
||||||
if (!EmitType(pre, value_ty, ast::StorageClass::kNone,
|
if (!EmitTypeAndName(pre, value_ty, ast::StorageClass::kNone,
|
||||||
ast::Access::kUndefined, "")) {
|
ast::Access::kUndefined, result)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pre << " " << result << " = ";
|
pre << " = ";
|
||||||
if (!EmitZeroValue(pre, value_ty)) {
|
if (!EmitZeroValue(pre, value_ty)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -725,11 +842,11 @@ bool GeneratorImpl::EmitStorageAtomicCall(
|
||||||
auto* value = expr->params()[3];
|
auto* value = expr->params()[3];
|
||||||
|
|
||||||
std::string compare = generate_name("atomic_compare_value");
|
std::string compare = generate_name("atomic_compare_value");
|
||||||
if (!EmitType(ss, TypeOf(compare_value), ast::StorageClass::kNone,
|
if (!EmitTypeAndName(ss, TypeOf(compare_value), ast::StorageClass::kNone,
|
||||||
ast::Access::kUndefined, "")) {
|
ast::Access::kUndefined, compare)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ss << " " << compare << " = ";
|
ss << " = ";
|
||||||
if (!EmitExpression(pre, ss, compare_value)) {
|
if (!EmitExpression(pre, ss, compare_value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -805,7 +922,7 @@ bool GeneratorImpl::EmitStorageAtomicCall(
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TINT_UNREACHABLE(diagnostics_)
|
TINT_UNREACHABLE(diagnostics_)
|
||||||
<< "unsupported atomic DecomposeStorageAccess::Intrinsic::Op: "
|
<< "unsupported atomic DecomposeMemoryAccess::Intrinsic::Op: "
|
||||||
<< static_cast<int>(op);
|
<< static_cast<int>(op);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -842,11 +959,11 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& pre,
|
||||||
std::string result = generate_name("atomic_result");
|
std::string result = generate_name("atomic_result");
|
||||||
|
|
||||||
if (!intrinsic->ReturnType()->Is<sem::Void>()) {
|
if (!intrinsic->ReturnType()->Is<sem::Void>()) {
|
||||||
if (!EmitType(ss, intrinsic->ReturnType(), ast::StorageClass::kNone,
|
if (!EmitTypeAndName(ss, intrinsic->ReturnType(), ast::StorageClass::kNone,
|
||||||
ast::Access::kUndefined, "")) {
|
ast::Access::kUndefined, result)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ss << " " << result << " = ";
|
ss << " = ";
|
||||||
if (!EmitZeroValue(ss, intrinsic->ReturnType())) {
|
if (!EmitZeroValue(ss, intrinsic->ReturnType())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -875,11 +992,11 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& pre,
|
||||||
// HLSL does not have an InterlockedStore, so we emulate it with
|
// HLSL does not have an InterlockedStore, so we emulate it with
|
||||||
// InterlockedExchange and discard the returned value
|
// InterlockedExchange and discard the returned value
|
||||||
auto* value_ty = intrinsic->Parameters()[1].type;
|
auto* value_ty = intrinsic->Parameters()[1].type;
|
||||||
if (!EmitType(pre, value_ty, ast::StorageClass::kNone,
|
if (!EmitTypeAndName(pre, value_ty, ast::StorageClass::kNone,
|
||||||
ast::Access::kUndefined, "")) {
|
ast::Access::kUndefined, result)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pre << " " << result << " = ";
|
pre << " = ";
|
||||||
if (!EmitZeroValue(pre, value_ty)) {
|
if (!EmitZeroValue(pre, value_ty)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -905,11 +1022,11 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& pre,
|
||||||
auto* value = expr->params()[2];
|
auto* value = expr->params()[2];
|
||||||
|
|
||||||
std::string compare = generate_name("atomic_compare_value");
|
std::string compare = generate_name("atomic_compare_value");
|
||||||
if (!EmitType(ss, TypeOf(compare_value), ast::StorageClass::kNone,
|
if (!EmitTypeAndName(ss, TypeOf(compare_value), ast::StorageClass::kNone,
|
||||||
ast::Access::kUndefined, "")) {
|
ast::Access::kUndefined, compare)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ss << " " << compare << " = ";
|
ss << " = ";
|
||||||
if (!EmitExpression(pre, ss, compare_value)) {
|
if (!EmitExpression(pre, ss, compare_value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1902,18 +2019,16 @@ bool GeneratorImpl::EmitFunction(std::ostream& out, ast::Function* func) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: WGSL only allows for StorageClass::kNone on parameters, however the
|
// Note: WGSL only allows for StorageClass::kNone on parameters, however the
|
||||||
// sanitizer transforms generates load / store functions for storage
|
// sanitizer transforms generates load / store functions for storage or
|
||||||
// buffers. These functions have a storage buffer parameter with
|
// uniform buffers. These functions have a buffer parameter with
|
||||||
// StorageClass::kStorage. This is required to correctly translate the
|
// StorageClass::kStorage or StorageClass::kUniform. This is required to
|
||||||
// parameter to [RW]ByteAddressBuffer.
|
// correctly translate the parameter to a [RW]ByteAddressBuffer for storage
|
||||||
if (!EmitType(out, type, v->StorageClass(), v->Access(),
|
// buffers and a uint4[N] for uniform buffers.
|
||||||
|
if (!EmitTypeAndName(
|
||||||
|
out, type, v->StorageClass(), v->Access(),
|
||||||
builder_.Symbols().NameFor(v->Declaration()->symbol()))) {
|
builder_.Symbols().NameFor(v->Declaration()->symbol()))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Array name is output as part of the type
|
|
||||||
if (!type->Is<sem::Array>()) {
|
|
||||||
out << " " << builder_.Symbols().NameFor(v->Declaration()->symbol());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out << ") ";
|
out << ") ";
|
||||||
|
@ -1959,26 +2074,28 @@ bool GeneratorImpl::EmitUniformVariable(std::ostream& out,
|
||||||
auto binding_point = decl->binding_point();
|
auto binding_point = decl->binding_point();
|
||||||
auto* type = var->Type()->UnwrapRef();
|
auto* type = var->Type()->UnwrapRef();
|
||||||
|
|
||||||
if (auto* strct = type->As<sem::Struct>()) {
|
auto* str = type->As<sem::Struct>();
|
||||||
out << "ConstantBuffer<"
|
if (!str) {
|
||||||
<< builder_.Symbols().NameFor(strct->Declaration()->name()) << "> "
|
// https://www.w3.org/TR/WGSL/#module-scope-variables
|
||||||
<< builder_.Symbols().NameFor(decl->symbol())
|
TINT_ICE(diagnostics_)
|
||||||
<< RegisterAndSpace('b', binding_point) << ";" << std::endl;
|
<< "variables with uniform storage must be structure";
|
||||||
} else {
|
}
|
||||||
auto name = "cbuffer_" + builder_.Symbols().NameFor(decl->symbol());
|
|
||||||
out << "cbuffer " << name << RegisterAndSpace('b', binding_point) << " {"
|
auto name = builder_.Symbols().NameFor(decl->symbol());
|
||||||
<< std::endl;
|
out << "cbuffer cbuffer_" << name << RegisterAndSpace('b', binding_point)
|
||||||
|
<< " {" << std::endl;
|
||||||
|
|
||||||
increment_indent();
|
increment_indent();
|
||||||
make_indent(out);
|
make_indent(out);
|
||||||
if (!EmitType(out, type, var->StorageClass(), var->Access(), "")) {
|
|
||||||
|
if (!EmitTypeAndName(out, type, ast::StorageClass::kUniform, var->Access(),
|
||||||
|
name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out << " " << builder_.Symbols().NameFor(decl->symbol()) << ";"
|
out << ";" << std::endl;
|
||||||
<< std::endl;
|
|
||||||
decrement_indent();
|
decrement_indent();
|
||||||
out << "};" << std::endl;
|
out << "};" << std::endl;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1988,12 +2105,12 @@ bool GeneratorImpl::EmitStorageVariable(std::ostream& out,
|
||||||
|
|
||||||
auto* decl = var->Declaration();
|
auto* decl = var->Declaration();
|
||||||
auto* type = var->Type()->UnwrapRef();
|
auto* type = var->Type()->UnwrapRef();
|
||||||
if (!EmitType(out, type, ast::StorageClass::kStorage, var->Access(), "")) {
|
if (!EmitTypeAndName(out, type, ast::StorageClass::kStorage, var->Access(),
|
||||||
|
builder_.Symbols().NameFor(decl->symbol()))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
out << " " << builder_.Symbols().NameFor(decl->symbol())
|
out << RegisterAndSpace(var->Access() == ast::Access::kRead ? 't' : 'u',
|
||||||
<< RegisterAndSpace(var->Access() == ast::Access::kRead ? 't' : 'u',
|
|
||||||
decl->binding_point())
|
decl->binding_point())
|
||||||
<< ";" << std::endl;
|
<< ";" << std::endl;
|
||||||
|
|
||||||
|
@ -2016,12 +2133,9 @@ bool GeneratorImpl::EmitHandleVariable(std::ostream& out,
|
||||||
|
|
||||||
auto name = builder_.Symbols().NameFor(decl->symbol());
|
auto name = builder_.Symbols().NameFor(decl->symbol());
|
||||||
auto* type = var->Type()->UnwrapRef();
|
auto* type = var->Type()->UnwrapRef();
|
||||||
if (!EmitType(out, type, var->StorageClass(), var->Access(), name)) {
|
if (!EmitTypeAndName(out, type, var->StorageClass(), var->Access(), name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!type->Is<sem::Array>()) {
|
|
||||||
out << " " << name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* register_space = nullptr;
|
const char* register_space = nullptr;
|
||||||
|
|
||||||
|
@ -2067,12 +2181,9 @@ bool GeneratorImpl::EmitPrivateVariable(std::ostream& out,
|
||||||
|
|
||||||
auto name = builder_.Symbols().NameFor(decl->symbol());
|
auto name = builder_.Symbols().NameFor(decl->symbol());
|
||||||
auto* type = var->Type()->UnwrapRef();
|
auto* type = var->Type()->UnwrapRef();
|
||||||
if (!EmitType(out, type, var->StorageClass(), var->Access(), name)) {
|
if (!EmitTypeAndName(out, type, var->StorageClass(), var->Access(), name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!type->Is<sem::Array>()) {
|
|
||||||
out << " " << name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (constructor_out.str().length()) {
|
if (constructor_out.str().length()) {
|
||||||
out << " = " << constructor_out.str();
|
out << " = " << constructor_out.str();
|
||||||
|
@ -2099,12 +2210,9 @@ bool GeneratorImpl::EmitWorkgroupVariable(std::ostream& out,
|
||||||
|
|
||||||
auto name = builder_.Symbols().NameFor(decl->symbol());
|
auto name = builder_.Symbols().NameFor(decl->symbol());
|
||||||
auto* type = var->Type()->UnwrapRef();
|
auto* type = var->Type()->UnwrapRef();
|
||||||
if (!EmitType(out, type, var->StorageClass(), var->Access(), name)) {
|
if (!EmitTypeAndName(out, type, var->StorageClass(), var->Access(), name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!type->Is<sem::Array>()) {
|
|
||||||
out << " " << name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (constructor_out.str().length()) {
|
if (constructor_out.str().length()) {
|
||||||
out << " = " << constructor_out.str();
|
out << " = " << constructor_out.str();
|
||||||
|
@ -2193,11 +2301,10 @@ bool GeneratorImpl::EmitEntryPointFunction(std::ostream& out,
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
if (!EmitType(out, type, sem->StorageClass(), sem->Access(), "")) {
|
if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
|
||||||
|
builder_.Symbols().NameFor(var->symbol()))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
out << " " << builder_.Symbols().NameFor(var->symbol());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out << ") {" << std::endl;
|
out << ") {" << std::endl;
|
||||||
|
@ -2467,13 +2574,31 @@ bool GeneratorImpl::EmitType(std::ostream& out,
|
||||||
const sem::Type* type,
|
const sem::Type* type,
|
||||||
ast::StorageClass storage_class,
|
ast::StorageClass storage_class,
|
||||||
ast::Access access,
|
ast::Access access,
|
||||||
const std::string& name) {
|
const std::string& name,
|
||||||
if (storage_class == ast::StorageClass::kStorage) {
|
bool* name_printed /* = nullptr */) {
|
||||||
|
switch (storage_class) {
|
||||||
|
case ast::StorageClass::kStorage:
|
||||||
if (access != ast::Access::kRead) {
|
if (access != ast::Access::kRead) {
|
||||||
out << "RW";
|
out << "RW";
|
||||||
}
|
}
|
||||||
out << "ByteAddressBuffer";
|
out << "ByteAddressBuffer";
|
||||||
return true;
|
return true;
|
||||||
|
case ast::StorageClass::kUniform: {
|
||||||
|
auto* str = type->As<sem::Struct>();
|
||||||
|
if (!str) {
|
||||||
|
// https://www.w3.org/TR/WGSL/#module-scope-variables
|
||||||
|
TINT_ICE(diagnostics_)
|
||||||
|
<< "variables with uniform storage must be structure";
|
||||||
|
}
|
||||||
|
auto array_length = (str->Size() + 15) / 16;
|
||||||
|
out << "uint4 " << name << "[" << array_length << "]";
|
||||||
|
if (name_printed) {
|
||||||
|
*name_printed = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto* ary = type->As<sem::Array>()) {
|
if (auto* ary = type->As<sem::Array>()) {
|
||||||
|
@ -2494,6 +2619,9 @@ bool GeneratorImpl::EmitType(std::ostream& out,
|
||||||
}
|
}
|
||||||
if (!name.empty()) {
|
if (!name.empty()) {
|
||||||
out << " " << name;
|
out << " " << name;
|
||||||
|
if (name_printed) {
|
||||||
|
*name_printed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (uint32_t size : sizes) {
|
for (uint32_t size : sizes) {
|
||||||
out << "[" << size << "]";
|
out << "[" << size << "]";
|
||||||
|
@ -2620,44 +2748,35 @@ bool GeneratorImpl::EmitType(std::ostream& out,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GeneratorImpl::EmitTypeAndName(std::ostream& out,
|
||||||
|
const sem::Type* type,
|
||||||
|
ast::StorageClass storage_class,
|
||||||
|
ast::Access access,
|
||||||
|
const std::string& name) {
|
||||||
|
bool printed_name = false;
|
||||||
|
if (!EmitType(out, type, storage_class, access, name, &printed_name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!name.empty() && !printed_name) {
|
||||||
|
out << " " << name;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) {
|
bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) {
|
||||||
auto storage_class_uses = str->StorageClassUsage();
|
auto storage_class_uses = str->StorageClassUsage();
|
||||||
if (storage_class_uses.size() ==
|
if (storage_class_uses.size() ==
|
||||||
storage_class_uses.count(ast::StorageClass::kStorage)) {
|
(storage_class_uses.count(ast::StorageClass::kStorage) +
|
||||||
// The only use of the structure is as a storage buffer.
|
storage_class_uses.count(ast::StorageClass::kUniform))) {
|
||||||
|
// The only use of the structure is as a storage buffer and / or uniform
|
||||||
|
// buffer.
|
||||||
// Structures used as storage buffer are read and written to via a
|
// Structures used as storage buffer are read and written to via a
|
||||||
// ByteAddressBuffer instead of true structure.
|
// ByteAddressBuffer instead of true structure.
|
||||||
|
// Structures used as uniform buffer are read from an array of vectors
|
||||||
|
// instead of true structure.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_host_shareable = str->IsHostShareable();
|
|
||||||
uint32_t hlsl_offset = 0;
|
|
||||||
|
|
||||||
// Emits a `/* 0xnnnn */` byte offset comment for a struct member.
|
|
||||||
auto add_byte_offset_comment = [&](uint32_t offset) {
|
|
||||||
std::ios_base::fmtflags saved_flag_state(out.flags());
|
|
||||||
out << "/* 0x" << std::hex << std::setfill('0') << std::setw(4) << offset
|
|
||||||
<< " */ ";
|
|
||||||
out.flags(saved_flag_state);
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t pad_count = 0;
|
|
||||||
auto add_padding = [&](uint32_t size) {
|
|
||||||
if (size & 3) {
|
|
||||||
TINT_ICE(builder_.Diagnostics())
|
|
||||||
<< "attempting to pad field with " << size
|
|
||||||
<< " bytes, but we require a multiple of 4 bytes";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::string name;
|
|
||||||
do {
|
|
||||||
name = "tint_pad_" + std::to_string(pad_count++);
|
|
||||||
} while (str->FindMember(builder_.Symbols().Get(name)));
|
|
||||||
|
|
||||||
out << "int " << name << "[" << (size / 4) << "];" << std::endl;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto struct_name = builder_.Symbols().NameFor(str->Declaration()->name());
|
auto struct_name = builder_.Symbols().NameFor(str->Declaration()->name());
|
||||||
out << "struct " << struct_name << " {" << std::endl;
|
out << "struct " << struct_name << " {" << std::endl;
|
||||||
|
|
||||||
|
@ -2666,40 +2785,13 @@ bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) {
|
||||||
make_indent(out);
|
make_indent(out);
|
||||||
|
|
||||||
auto name = builder_.Symbols().NameFor(mem->Declaration()->symbol());
|
auto name = builder_.Symbols().NameFor(mem->Declaration()->symbol());
|
||||||
auto wgsl_offset = mem->Offset();
|
|
||||||
|
|
||||||
if (is_host_shareable) {
|
|
||||||
if (wgsl_offset < hlsl_offset) {
|
|
||||||
// Unimplementable layout
|
|
||||||
TINT_ICE(diagnostics_)
|
|
||||||
<< "Structure member WGSL offset (" << wgsl_offset
|
|
||||||
<< ") is behind HLSL offset (" << hlsl_offset << ")";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate padding if required
|
|
||||||
if (auto padding = wgsl_offset - hlsl_offset) {
|
|
||||||
add_byte_offset_comment(hlsl_offset);
|
|
||||||
if (!add_padding(padding)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
hlsl_offset += padding;
|
|
||||||
make_indent(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
add_byte_offset_comment(hlsl_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* ty = mem->Type();
|
auto* ty = mem->Type();
|
||||||
|
|
||||||
if (!EmitType(out, ty, ast::StorageClass::kNone, ast::Access::kReadWrite,
|
if (!EmitTypeAndName(out, ty, ast::StorageClass::kNone,
|
||||||
name)) {
|
ast::Access::kReadWrite, name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Array member name will be output with the type
|
|
||||||
if (!ty->Is<sem::Array>()) {
|
|
||||||
out << " " << name;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* deco : mem->Declaration()->decorations()) {
|
for (auto* deco : mem->Declaration()->decorations()) {
|
||||||
if (auto* location = deco->As<ast::LocationDecoration>()) {
|
if (auto* location = deco->As<ast::LocationDecoration>()) {
|
||||||
|
@ -2733,26 +2825,6 @@ bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
out << ";" << std::endl;
|
out << ";" << std::endl;
|
||||||
|
|
||||||
if (is_host_shareable) {
|
|
||||||
// Calculate new HLSL offset
|
|
||||||
auto size_align = HlslPackedTypeSizeAndAlign(ty);
|
|
||||||
if (hlsl_offset % size_align.align) {
|
|
||||||
TINT_ICE(diagnostics_)
|
|
||||||
<< "Misaligned HLSL structure member "
|
|
||||||
<< ty->FriendlyName(builder_.Symbols()) << " " << name;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
hlsl_offset += size_align.size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_host_shareable && str->Size() != hlsl_offset) {
|
|
||||||
make_indent(out);
|
|
||||||
add_byte_offset_comment(hlsl_offset);
|
|
||||||
if (!add_padding(str->Size() - hlsl_offset)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decrement_indent();
|
decrement_indent();
|
||||||
|
@ -2760,57 +2832,6 @@ bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) {
|
||||||
|
|
||||||
out << "};" << std::endl;
|
out << "};" << std::endl;
|
||||||
|
|
||||||
// If the structure has padding members, create a helper function for building
|
|
||||||
// the structure.
|
|
||||||
if (pad_count) {
|
|
||||||
auto builder_name = generate_name("make_" + struct_name);
|
|
||||||
|
|
||||||
out << std::endl;
|
|
||||||
out << struct_name << " " << builder_name << "(";
|
|
||||||
uint32_t idx = 0;
|
|
||||||
for (auto* mem : str->Members()) {
|
|
||||||
if (idx > 0) {
|
|
||||||
out << ",";
|
|
||||||
make_indent(out << std::endl);
|
|
||||||
out << std::string(struct_name.length() + builder_name.length() + 2,
|
|
||||||
' ');
|
|
||||||
}
|
|
||||||
auto name = "param_" + std::to_string(idx++);
|
|
||||||
auto* ty = mem->Type();
|
|
||||||
if (!EmitType(out, ty, ast::StorageClass::kNone, ast::Access::kReadWrite,
|
|
||||||
name)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Array member name will be output with the type
|
|
||||||
if (!ty->Is<sem::Array>()) {
|
|
||||||
out << " " << name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out << ") {";
|
|
||||||
increment_indent();
|
|
||||||
make_indent(out << std::endl);
|
|
||||||
|
|
||||||
out << struct_name << " output;";
|
|
||||||
make_indent(out << std::endl);
|
|
||||||
idx = 0;
|
|
||||||
for (auto* mem : str->Members()) {
|
|
||||||
out << "output."
|
|
||||||
<< builder_.Symbols().NameFor(mem->Declaration()->symbol()) << " = "
|
|
||||||
<< "param_" + std::to_string(idx++) << ";";
|
|
||||||
make_indent(out << std::endl);
|
|
||||||
}
|
|
||||||
out << "return output;";
|
|
||||||
|
|
||||||
decrement_indent();
|
|
||||||
make_indent(out << std::endl);
|
|
||||||
out << "}";
|
|
||||||
|
|
||||||
make_indent(out << std::endl);
|
|
||||||
|
|
||||||
structure_builders_[str] = builder_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2872,13 +2893,10 @@ bool GeneratorImpl::EmitVariable(std::ostream& out, ast::Variable* var) {
|
||||||
if (var->is_const()) {
|
if (var->is_const()) {
|
||||||
out << "const ";
|
out << "const ";
|
||||||
}
|
}
|
||||||
if (!EmitType(out, type, sem->StorageClass(), sem->Access(),
|
if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
|
||||||
builder_.Symbols().NameFor(var->symbol()))) {
|
builder_.Symbols().NameFor(var->symbol()))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!type->Is<sem::Array>()) {
|
|
||||||
out << " " << builder_.Symbols().NameFor(var->symbol());
|
|
||||||
}
|
|
||||||
out << constructor_out.str() << ";" << std::endl;
|
out << constructor_out.str() << ";" << std::endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2925,21 +2943,17 @@ bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out,
|
||||||
}
|
}
|
||||||
out << "#endif" << std::endl;
|
out << "#endif" << std::endl;
|
||||||
out << "static const ";
|
out << "static const ";
|
||||||
if (!EmitType(out, type, sem->StorageClass(), sem->Access(),
|
if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
|
||||||
builder_.Symbols().NameFor(var->symbol()))) {
|
builder_.Symbols().NameFor(var->symbol()))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out << " " << builder_.Symbols().NameFor(var->symbol()) << " = "
|
out << " = " << kSpecConstantPrefix << const_id << ";" << std::endl;
|
||||||
<< kSpecConstantPrefix << const_id << ";" << std::endl;
|
|
||||||
} else {
|
} else {
|
||||||
out << "static const ";
|
out << "static const ";
|
||||||
if (!EmitType(out, type, sem->StorageClass(), sem->Access(),
|
if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
|
||||||
builder_.Symbols().NameFor(var->symbol()))) {
|
builder_.Symbols().NameFor(var->symbol()))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!type->Is<sem::Array>()) {
|
|
||||||
out << " " << builder_.Symbols().NameFor(var->symbol());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var->constructor() != nullptr) {
|
if (var->constructor() != nullptr) {
|
||||||
out << " = " << constructor_out.str();
|
out << " = " << constructor_out.str();
|
||||||
|
@ -2982,63 +2996,6 @@ bool GeneratorImpl::EmitBlockBraces(std::ostream& out,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
|
|
||||||
// TODO(crbug.com/tint/898): We need CTS and / or Dawn e2e tests for this logic.
|
|
||||||
GeneratorImpl::SizeAndAlign GeneratorImpl::HlslPackedTypeSizeAndAlign(
|
|
||||||
const sem::Type* ty) {
|
|
||||||
if (ty->IsAnyOf<sem::U32, sem::I32, sem::F32>()) {
|
|
||||||
return {4, 4};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* vec = ty->As<sem::Vector>()) {
|
|
||||||
auto num_els = vec->size();
|
|
||||||
auto* el_ty = vec->type();
|
|
||||||
if (el_ty->IsAnyOf<sem::U32, sem::I32, sem::F32>()) {
|
|
||||||
return SizeAndAlign{num_els * 4, 4};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* mat = ty->As<sem::Matrix>()) {
|
|
||||||
auto cols = mat->columns();
|
|
||||||
auto rows = mat->rows();
|
|
||||||
auto* el_ty = mat->type();
|
|
||||||
if (el_ty->IsAnyOf<sem::U32, sem::I32, sem::F32>()) {
|
|
||||||
static constexpr SizeAndAlign table[] = {
|
|
||||||
/* float2x2 */ {16, 8},
|
|
||||||
/* float2x3 */ {32, 16},
|
|
||||||
/* float2x4 */ {32, 16},
|
|
||||||
/* float3x2 */ {24, 8},
|
|
||||||
/* float3x3 */ {48, 16},
|
|
||||||
/* float3x4 */ {48, 16},
|
|
||||||
/* float4x2 */ {32, 8},
|
|
||||||
/* float4x3 */ {64, 16},
|
|
||||||
/* float4x4 */ {64, 16},
|
|
||||||
};
|
|
||||||
if (cols >= 2 && cols <= 4 && rows >= 2 && rows <= 4) {
|
|
||||||
return table[(3 * (cols - 2)) + (rows - 2)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* arr = ty->As<sem::Array>()) {
|
|
||||||
auto el_size_align = HlslPackedTypeSizeAndAlign(arr->ElemType());
|
|
||||||
if (!arr->IsStrideImplicit()) {
|
|
||||||
TINT_ICE(diagnostics_) << "arrays with explicit strides should have "
|
|
||||||
"removed with the PadArrayElements transform";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
auto num_els = std::max<uint32_t>(arr->Count(), 1);
|
|
||||||
return SizeAndAlign{el_size_align.size * num_els, el_size_align.align};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* str = ty->As<sem::Struct>()) {
|
|
||||||
return SizeAndAlign{str->Size(), str->Align()};
|
|
||||||
}
|
|
||||||
|
|
||||||
TINT_UNREACHABLE(diagnostics_) << "Unhandled type " << ty->TypeInfo().name;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace hlsl
|
} // namespace hlsl
|
||||||
} // namespace writer
|
} // namespace writer
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include "src/ast/unary_op_expression.h"
|
#include "src/ast/unary_op_expression.h"
|
||||||
#include "src/program_builder.h"
|
#include "src/program_builder.h"
|
||||||
#include "src/scope_stack.h"
|
#include "src/scope_stack.h"
|
||||||
#include "src/transform/decompose_storage_access.h"
|
#include "src/transform/decompose_memory_access.h"
|
||||||
#include "src/writer/text_generator.h"
|
#include "src/writer/text_generator.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -117,17 +117,29 @@ class GeneratorImpl : public TextGenerator {
|
||||||
std::ostream& out,
|
std::ostream& out,
|
||||||
ast::CallExpression* expr);
|
ast::CallExpression* expr);
|
||||||
/// Handles generating a call expression to a
|
/// Handles generating a call expression to a
|
||||||
/// transform::DecomposeStorageAccess::Intrinsic
|
/// transform::DecomposeMemoryAccess::Intrinsic for a uniform buffer
|
||||||
/// @param pre the preamble for the expression stream
|
/// @param pre the preamble for the expression stream
|
||||||
/// @param out the output of the expression stream
|
/// @param out the output of the expression stream
|
||||||
/// @param expr the call expression
|
/// @param expr the call expression
|
||||||
/// @param intrinsic the transform::DecomposeStorageAccess::Intrinsic
|
/// @param intrinsic the transform::DecomposeMemoryAccess::Intrinsic
|
||||||
/// @returns true if the call expression is emitted
|
/// @returns true if the call expression is emitted
|
||||||
bool EmitDecomposeStorageAccessIntrinsic(
|
bool EmitUniformBufferAccess(
|
||||||
std::ostream& pre,
|
std::ostream& pre,
|
||||||
std::ostream& out,
|
std::ostream& out,
|
||||||
ast::CallExpression* expr,
|
ast::CallExpression* expr,
|
||||||
const transform::DecomposeStorageAccess::Intrinsic* intrinsic);
|
const transform::DecomposeMemoryAccess::Intrinsic* intrinsic);
|
||||||
|
/// Handles generating a call expression to a
|
||||||
|
/// transform::DecomposeMemoryAccess::Intrinsic for a storage buffer
|
||||||
|
/// @param pre the preamble for the expression stream
|
||||||
|
/// @param out the output of the expression stream
|
||||||
|
/// @param expr the call expression
|
||||||
|
/// @param intrinsic the transform::DecomposeMemoryAccess::Intrinsic
|
||||||
|
/// @returns true if the call expression is emitted
|
||||||
|
bool EmitStorageBufferAccess(
|
||||||
|
std::ostream& pre,
|
||||||
|
std::ostream& out,
|
||||||
|
ast::CallExpression* expr,
|
||||||
|
const transform::DecomposeMemoryAccess::Intrinsic* intrinsic);
|
||||||
/// Handles generating a barrier intrinsic call
|
/// Handles generating a barrier intrinsic call
|
||||||
/// @param pre the preamble for the expression stream
|
/// @param pre the preamble for the expression stream
|
||||||
/// @param out the output of the expression stream
|
/// @param out the output of the expression stream
|
||||||
|
@ -146,7 +158,7 @@ class GeneratorImpl : public TextGenerator {
|
||||||
std::ostream& pre,
|
std::ostream& pre,
|
||||||
std::ostream& out,
|
std::ostream& out,
|
||||||
ast::CallExpression* expr,
|
ast::CallExpression* expr,
|
||||||
transform::DecomposeStorageAccess::Intrinsic::Op op);
|
transform::DecomposeMemoryAccess::Intrinsic::Op op);
|
||||||
/// Handles generating an atomic intrinsic call for a workgroup variable
|
/// Handles generating an atomic intrinsic call for a workgroup variable
|
||||||
/// @param pre the preamble for the expression stream
|
/// @param pre the preamble for the expression stream
|
||||||
/// @param out the output of the expression stream
|
/// @param out the output of the expression stream
|
||||||
|
@ -361,9 +373,24 @@ class GeneratorImpl : public TextGenerator {
|
||||||
/// @param type the type to generate
|
/// @param type the type to generate
|
||||||
/// @param storage_class the storage class of the variable
|
/// @param storage_class the storage class of the variable
|
||||||
/// @param access the access control type of the variable
|
/// @param access the access control type of the variable
|
||||||
/// @param name the name of the variable, only used for array emission
|
/// @param name the name of the variable, used for array emission.
|
||||||
|
/// @param name_printed (optional) if not nullptr and an array was printed
|
||||||
|
/// then the boolean is set to true.
|
||||||
/// @returns true if the type is emitted
|
/// @returns true if the type is emitted
|
||||||
bool EmitType(std::ostream& out,
|
bool EmitType(std::ostream& out,
|
||||||
|
const sem::Type* type,
|
||||||
|
ast::StorageClass storage_class,
|
||||||
|
ast::Access access,
|
||||||
|
const std::string& name,
|
||||||
|
bool* name_printed = nullptr);
|
||||||
|
/// Handles generating type and name
|
||||||
|
/// @param out the output stream
|
||||||
|
/// @param type the type to generate
|
||||||
|
/// @param storage_class the storage class of the variable
|
||||||
|
/// @param access the access control type of the variable
|
||||||
|
/// @param name the name of the variable, used for array emission.
|
||||||
|
/// @returns true if the type is emitted
|
||||||
|
bool EmitTypeAndName(std::ostream& out,
|
||||||
const sem::Type* type,
|
const sem::Type* type,
|
||||||
ast::StorageClass storage_class,
|
ast::StorageClass storage_class,
|
||||||
ast::Access access,
|
ast::Access access,
|
||||||
|
@ -460,16 +487,6 @@ class GeneratorImpl : public TextGenerator {
|
||||||
return EmitBlockBraces(out, "", std::forward<F>(cb));
|
return EmitBlockBraces(out, "", std::forward<F>(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
// A pair of byte size and alignment `uint32_t`s.
|
|
||||||
struct SizeAndAlign {
|
|
||||||
uint32_t size;
|
|
||||||
uint32_t align;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @returns the HLSL packed type size and alignment in bytes for the given
|
|
||||||
/// type.
|
|
||||||
SizeAndAlign HlslPackedTypeSizeAndAlign(const sem::Type* ty);
|
|
||||||
|
|
||||||
ProgramBuilder builder_;
|
ProgramBuilder builder_;
|
||||||
std::function<bool(std::ostream& out)> emit_continuing_;
|
std::function<bool(std::ostream& out)> emit_continuing_;
|
||||||
std::unordered_map<const sem::Struct*, std::string> structure_builders_;
|
std::unordered_map<const sem::Struct*, std::string> structure_builders_;
|
||||||
|
|
|
@ -341,12 +341,10 @@ TEST_F(HlslGeneratorImplTest_Function,
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
||||||
EXPECT_EQ(result(), R"(struct UBO {
|
EXPECT_EQ(result(), R"(cbuffer cbuffer_ubo : register(b0, space1) {
|
||||||
/* 0x0000 */ float4 coord;
|
uint4 ubo[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
ConstantBuffer<UBO> ubo : register(b0, space1);
|
|
||||||
|
|
||||||
float sub_func(float param) {
|
float sub_func(float param) {
|
||||||
return ubo.coord.x;
|
return ubo.coord.x;
|
||||||
}
|
}
|
||||||
|
@ -384,12 +382,10 @@ TEST_F(HlslGeneratorImplTest_Function,
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
||||||
EXPECT_EQ(result(), R"(struct Uniforms {
|
EXPECT_EQ(result(), R"(cbuffer cbuffer_uniforms : register(b0, space1) {
|
||||||
/* 0x0000 */ float4 coord;
|
uint4 uniforms[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
ConstantBuffer<Uniforms> uniforms : register(b0, space1);
|
|
||||||
|
|
||||||
void frag_main() {
|
void frag_main() {
|
||||||
float v = uniforms.coord.x;
|
float v = uniforms.coord.x;
|
||||||
return;
|
return;
|
||||||
|
@ -583,12 +579,10 @@ TEST_F(HlslGeneratorImplTest_Function,
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
||||||
EXPECT_EQ(result(), R"(struct S {
|
EXPECT_EQ(result(), R"(cbuffer cbuffer_coord : register(b0, space1) {
|
||||||
/* 0x0000 */ float x;
|
uint4 coord[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
ConstantBuffer<S> coord : register(b0, space1);
|
|
||||||
|
|
||||||
float sub_func(float param) {
|
float sub_func(float param) {
|
||||||
return coord.x;
|
return coord.x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,31 +93,6 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Array_WithoutName) {
|
||||||
EXPECT_EQ(result(), "bool[4]");
|
EXPECT_EQ(result(), "bool[4]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayWithStride) {
|
|
||||||
auto* s = Structure("s", {Member("arr", ty.array<f32, 4>(64))},
|
|
||||||
{create<ast::StructBlockDecoration>()});
|
|
||||||
auto* ubo = Global("ubo", ty.Of(s), ast::StorageClass::kUniform,
|
|
||||||
ast::DecorationList{
|
|
||||||
create<ast::GroupDecoration>(1),
|
|
||||||
create<ast::BindingDecoration>(1),
|
|
||||||
});
|
|
||||||
WrapInFunction(MemberAccessor(ubo, "arr"));
|
|
||||||
|
|
||||||
GeneratorImpl& gen = SanitizeAndBuild();
|
|
||||||
|
|
||||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
|
||||||
EXPECT_THAT(result(), HasSubstr(R"(struct tint_padded_array_element {
|
|
||||||
/* 0x0000 */ float el;
|
|
||||||
/* 0x0004 */ int tint_pad_0[15];
|
|
||||||
};)"));
|
|
||||||
EXPECT_THAT(result(), HasSubstr(R"(struct tint_array_wrapper {
|
|
||||||
/* 0x0000 */ tint_padded_array_element arr[4];
|
|
||||||
};)"));
|
|
||||||
EXPECT_THAT(result(), HasSubstr(R"(struct s {
|
|
||||||
/* 0x0000 */ tint_array_wrapper arr;
|
|
||||||
};)"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Type, EmitType_Bool) {
|
TEST_F(HlslGeneratorImplTest_Type, EmitType_Bool) {
|
||||||
auto* bool_ = create<sem::Bool>();
|
auto* bool_ = create<sem::Bool>();
|
||||||
|
|
||||||
|
@ -232,430 +207,6 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) {
|
||||||
EXPECT_EQ(result(), "S");
|
EXPECT_EQ(result(), "S");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_Layout_NonComposites) {
|
|
||||||
auto* s =
|
|
||||||
Structure("S",
|
|
||||||
{
|
|
||||||
Member("a", ty.i32(), {MemberSize(32)}),
|
|
||||||
Member("b", ty.f32(), {MemberAlign(128), MemberSize(128)}),
|
|
||||||
Member("c", ty.vec2<f32>()),
|
|
||||||
Member("d", ty.u32()),
|
|
||||||
Member("e", ty.vec3<f32>()),
|
|
||||||
Member("f", ty.u32()),
|
|
||||||
Member("g", ty.vec4<f32>()),
|
|
||||||
Member("h", ty.u32()),
|
|
||||||
Member("i", ty.mat2x2<f32>()),
|
|
||||||
Member("j", ty.u32()),
|
|
||||||
Member("k", ty.mat2x3<f32>()),
|
|
||||||
Member("l", ty.u32()),
|
|
||||||
Member("m", ty.mat2x4<f32>()),
|
|
||||||
Member("n", ty.u32()),
|
|
||||||
Member("o", ty.mat3x2<f32>()),
|
|
||||||
Member("p", ty.u32()),
|
|
||||||
Member("q", ty.mat3x3<f32>()),
|
|
||||||
Member("r", ty.u32()),
|
|
||||||
Member("s", ty.mat3x4<f32>()),
|
|
||||||
Member("t", ty.u32()),
|
|
||||||
Member("u", ty.mat4x2<f32>()),
|
|
||||||
Member("v", ty.u32()),
|
|
||||||
Member("w", ty.mat4x3<f32>()),
|
|
||||||
Member("x", ty.u32()),
|
|
||||||
Member("y", ty.mat4x4<f32>()),
|
|
||||||
Member("z", ty.f32()),
|
|
||||||
},
|
|
||||||
{create<ast::StructBlockDecoration>()});
|
|
||||||
|
|
||||||
Global("G", ty.Of(s), ast::StorageClass::kUniform,
|
|
||||||
ast::DecorationList{
|
|
||||||
create<ast::BindingDecoration>(0),
|
|
||||||
create<ast::GroupDecoration>(0),
|
|
||||||
});
|
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
|
||||||
|
|
||||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
|
||||||
ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error();
|
|
||||||
|
|
||||||
auto* expect = R"(struct S {
|
|
||||||
/* 0x0000 */ int a;
|
|
||||||
/* 0x0004 */ int tint_pad_0[31];
|
|
||||||
/* 0x0080 */ float b;
|
|
||||||
/* 0x0084 */ int tint_pad_1[31];
|
|
||||||
/* 0x0100 */ float2 c;
|
|
||||||
/* 0x0108 */ uint d;
|
|
||||||
/* 0x010c */ int tint_pad_2[1];
|
|
||||||
/* 0x0110 */ float3 e;
|
|
||||||
/* 0x011c */ uint f;
|
|
||||||
/* 0x0120 */ float4 g;
|
|
||||||
/* 0x0130 */ uint h;
|
|
||||||
/* 0x0134 */ int tint_pad_3[1];
|
|
||||||
/* 0x0138 */ float2x2 i;
|
|
||||||
/* 0x0148 */ uint j;
|
|
||||||
/* 0x014c */ int tint_pad_4[1];
|
|
||||||
/* 0x0150 */ float2x3 k;
|
|
||||||
/* 0x0170 */ uint l;
|
|
||||||
/* 0x0174 */ int tint_pad_5[3];
|
|
||||||
/* 0x0180 */ float2x4 m;
|
|
||||||
/* 0x01a0 */ uint n;
|
|
||||||
/* 0x01a4 */ int tint_pad_6[1];
|
|
||||||
/* 0x01a8 */ float3x2 o;
|
|
||||||
/* 0x01c0 */ uint p;
|
|
||||||
/* 0x01c4 */ int tint_pad_7[3];
|
|
||||||
/* 0x01d0 */ float3x3 q;
|
|
||||||
/* 0x0200 */ uint r;
|
|
||||||
/* 0x0204 */ int tint_pad_8[3];
|
|
||||||
/* 0x0210 */ float3x4 s;
|
|
||||||
/* 0x0240 */ uint t;
|
|
||||||
/* 0x0244 */ int tint_pad_9[1];
|
|
||||||
/* 0x0248 */ float4x2 u;
|
|
||||||
/* 0x0268 */ uint v;
|
|
||||||
/* 0x026c */ int tint_pad_10[1];
|
|
||||||
/* 0x0270 */ float4x3 w;
|
|
||||||
/* 0x02b0 */ uint x;
|
|
||||||
/* 0x02b4 */ int tint_pad_11[3];
|
|
||||||
/* 0x02c0 */ float4x4 y;
|
|
||||||
/* 0x0300 */ float z;
|
|
||||||
/* 0x0304 */ int tint_pad_12[31];
|
|
||||||
};
|
|
||||||
|
|
||||||
S make_S(int param_0,
|
|
||||||
float param_1,
|
|
||||||
float2 param_2,
|
|
||||||
uint param_3,
|
|
||||||
float3 param_4,
|
|
||||||
uint param_5,
|
|
||||||
float4 param_6,
|
|
||||||
uint param_7,
|
|
||||||
float2x2 param_8,
|
|
||||||
uint param_9,
|
|
||||||
float2x3 param_10,
|
|
||||||
uint param_11,
|
|
||||||
float2x4 param_12,
|
|
||||||
uint param_13,
|
|
||||||
float3x2 param_14,
|
|
||||||
uint param_15,
|
|
||||||
float3x3 param_16,
|
|
||||||
uint param_17,
|
|
||||||
float3x4 param_18,
|
|
||||||
uint param_19,
|
|
||||||
float4x2 param_20,
|
|
||||||
uint param_21,
|
|
||||||
float4x3 param_22,
|
|
||||||
uint param_23,
|
|
||||||
float4x4 param_24,
|
|
||||||
float param_25) {
|
|
||||||
S output;
|
|
||||||
output.a = param_0;
|
|
||||||
output.b = param_1;
|
|
||||||
output.c = param_2;
|
|
||||||
output.d = param_3;
|
|
||||||
output.e = param_4;
|
|
||||||
output.f = param_5;
|
|
||||||
output.g = param_6;
|
|
||||||
output.h = param_7;
|
|
||||||
output.i = param_8;
|
|
||||||
output.j = param_9;
|
|
||||||
output.k = param_10;
|
|
||||||
output.l = param_11;
|
|
||||||
output.m = param_12;
|
|
||||||
output.n = param_13;
|
|
||||||
output.o = param_14;
|
|
||||||
output.p = param_15;
|
|
||||||
output.q = param_16;
|
|
||||||
output.r = param_17;
|
|
||||||
output.s = param_18;
|
|
||||||
output.t = param_19;
|
|
||||||
output.u = param_20;
|
|
||||||
output.v = param_21;
|
|
||||||
output.w = param_22;
|
|
||||||
output.x = param_23;
|
|
||||||
output.y = param_24;
|
|
||||||
output.z = param_25;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
EXPECT_EQ(result(), expect);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_Layout_Structures) {
|
|
||||||
// inner_x: size(1024), align(512)
|
|
||||||
auto* inner_x =
|
|
||||||
Structure("inner_x", {
|
|
||||||
Member("a", ty.i32()),
|
|
||||||
Member("b", ty.f32(), {MemberAlign(512)}),
|
|
||||||
});
|
|
||||||
|
|
||||||
// inner_y: size(516), align(4)
|
|
||||||
auto* inner_y =
|
|
||||||
Structure("inner_y", {
|
|
||||||
Member("a", ty.i32(), {MemberSize(512)}),
|
|
||||||
Member("b", ty.f32()),
|
|
||||||
});
|
|
||||||
|
|
||||||
auto* s = Structure("S",
|
|
||||||
{
|
|
||||||
Member("a", ty.i32()),
|
|
||||||
Member("b", ty.Of(inner_x)),
|
|
||||||
Member("c", ty.f32()),
|
|
||||||
Member("d", ty.Of(inner_y)),
|
|
||||||
Member("e", ty.f32()),
|
|
||||||
},
|
|
||||||
{create<ast::StructBlockDecoration>()});
|
|
||||||
|
|
||||||
Global("G", ty.Of(s), ast::StorageClass::kUniform,
|
|
||||||
ast::DecorationList{
|
|
||||||
create<ast::BindingDecoration>(0),
|
|
||||||
create<ast::GroupDecoration>(0),
|
|
||||||
});
|
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
|
||||||
|
|
||||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
|
||||||
ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error();
|
|
||||||
|
|
||||||
auto* expect = R"(struct S {
|
|
||||||
/* 0x0000 */ int a;
|
|
||||||
/* 0x0004 */ int tint_pad_0[127];
|
|
||||||
/* 0x0200 */ inner_x b;
|
|
||||||
/* 0x0600 */ float c;
|
|
||||||
/* 0x0604 */ inner_y d;
|
|
||||||
/* 0x0808 */ float e;
|
|
||||||
/* 0x080c */ int tint_pad_1[125];
|
|
||||||
};
|
|
||||||
|
|
||||||
S make_S(int param_0,
|
|
||||||
inner_x param_1,
|
|
||||||
float param_2,
|
|
||||||
inner_y param_3,
|
|
||||||
float param_4) {
|
|
||||||
S output;
|
|
||||||
output.a = param_0;
|
|
||||||
output.b = param_1;
|
|
||||||
output.c = param_2;
|
|
||||||
output.d = param_3;
|
|
||||||
output.e = param_4;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
EXPECT_EQ(result(), expect);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_Layout_ArrayDefaultStride) {
|
|
||||||
// inner: size(1024), align(512)
|
|
||||||
auto* inner =
|
|
||||||
Structure("inner", {
|
|
||||||
Member("a", ty.i32()),
|
|
||||||
Member("b", ty.f32(), {MemberAlign(512)}),
|
|
||||||
});
|
|
||||||
|
|
||||||
// array_x: size(28), align(4)
|
|
||||||
auto* array_x = ty.array<f32, 7>();
|
|
||||||
|
|
||||||
// array_y: size(4096), align(512)
|
|
||||||
auto* array_y = ty.array(ty.Of(inner), 4);
|
|
||||||
|
|
||||||
// array_z: size(4), align(4)
|
|
||||||
auto* array_z = ty.array<f32, 1>();
|
|
||||||
|
|
||||||
auto* s =
|
|
||||||
Structure("S",
|
|
||||||
{
|
|
||||||
Member("a", ty.i32()),
|
|
||||||
Member("b", array_x),
|
|
||||||
Member("c", ty.f32()),
|
|
||||||
Member("d", array_y),
|
|
||||||
Member("e", ty.f32()),
|
|
||||||
Member("f", array_z),
|
|
||||||
},
|
|
||||||
ast::DecorationList{create<ast::StructBlockDecoration>()});
|
|
||||||
|
|
||||||
Global("G", ty.Of(s), ast::StorageClass::kUniform,
|
|
||||||
ast::DecorationList{
|
|
||||||
create<ast::BindingDecoration>(0),
|
|
||||||
create<ast::GroupDecoration>(0),
|
|
||||||
});
|
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
|
||||||
|
|
||||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
|
||||||
ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error();
|
|
||||||
|
|
||||||
auto* expect = R"(struct S {
|
|
||||||
/* 0x0000 */ int a;
|
|
||||||
/* 0x0004 */ float b[7];
|
|
||||||
/* 0x0020 */ float c;
|
|
||||||
/* 0x0024 */ int tint_pad_0[119];
|
|
||||||
/* 0x0200 */ inner d[4];
|
|
||||||
/* 0x1200 */ float e;
|
|
||||||
/* 0x1204 */ float f[1];
|
|
||||||
/* 0x1208 */ int tint_pad_1[126];
|
|
||||||
};
|
|
||||||
|
|
||||||
S make_S(int param_0,
|
|
||||||
float param_1[7],
|
|
||||||
float param_2,
|
|
||||||
inner param_3[4],
|
|
||||||
float param_4,
|
|
||||||
float param_5[1]) {
|
|
||||||
S output;
|
|
||||||
output.a = param_0;
|
|
||||||
output.b = param_1;
|
|
||||||
output.c = param_2;
|
|
||||||
output.d = param_3;
|
|
||||||
output.e = param_4;
|
|
||||||
output.f = param_5;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
EXPECT_EQ(result(), expect);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Type, AttemptTintPadSymbolCollision) {
|
|
||||||
auto* s = Structure(
|
|
||||||
"S",
|
|
||||||
{
|
|
||||||
// uses symbols tint_pad_[0..9] and tint_pad_[20..35]
|
|
||||||
Member("tint_pad_2", ty.i32(), {MemberSize(32)}),
|
|
||||||
Member("tint_pad_20", ty.f32(), {MemberAlign(128), MemberSize(128)}),
|
|
||||||
Member("tint_pad_33", ty.vec2<f32>()),
|
|
||||||
Member("tint_pad_1", ty.u32()),
|
|
||||||
Member("tint_pad_3", ty.vec3<f32>()),
|
|
||||||
Member("tint_pad_7", ty.u32()),
|
|
||||||
Member("tint_pad_25", ty.vec4<f32>()),
|
|
||||||
Member("tint_pad_5", ty.u32()),
|
|
||||||
Member("tint_pad_27", ty.mat2x2<f32>()),
|
|
||||||
Member("tint_pad_24", ty.u32()),
|
|
||||||
Member("tint_pad_23", ty.mat2x3<f32>()),
|
|
||||||
Member("tint_pad_0", ty.u32()),
|
|
||||||
Member("tint_pad_8", ty.mat2x4<f32>()),
|
|
||||||
Member("tint_pad_26", ty.u32()),
|
|
||||||
Member("tint_pad_29", ty.mat3x2<f32>()),
|
|
||||||
Member("tint_pad_6", ty.u32()),
|
|
||||||
Member("tint_pad_22", ty.mat3x3<f32>()),
|
|
||||||
Member("tint_pad_32", ty.u32()),
|
|
||||||
Member("tint_pad_34", ty.mat3x4<f32>()),
|
|
||||||
Member("tint_pad_35", ty.u32()),
|
|
||||||
Member("tint_pad_30", ty.mat4x2<f32>()),
|
|
||||||
Member("tint_pad_9", ty.u32()),
|
|
||||||
Member("tint_pad_31", ty.mat4x3<f32>()),
|
|
||||||
Member("tint_pad_28", ty.u32()),
|
|
||||||
Member("tint_pad_4", ty.mat4x4<f32>()),
|
|
||||||
Member("tint_pad_21", ty.f32()),
|
|
||||||
},
|
|
||||||
{create<ast::StructBlockDecoration>()});
|
|
||||||
|
|
||||||
Global("G", ty.Of(s), ast::StorageClass::kUniform,
|
|
||||||
ast::DecorationList{
|
|
||||||
create<ast::BindingDecoration>(0),
|
|
||||||
create<ast::GroupDecoration>(0),
|
|
||||||
});
|
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
|
||||||
|
|
||||||
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
|
|
||||||
ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error();
|
|
||||||
EXPECT_EQ(result(), R"(struct S {
|
|
||||||
/* 0x0000 */ int tint_pad_2;
|
|
||||||
/* 0x0004 */ int tint_pad_10[31];
|
|
||||||
/* 0x0080 */ float tint_pad_20;
|
|
||||||
/* 0x0084 */ int tint_pad_11[31];
|
|
||||||
/* 0x0100 */ float2 tint_pad_33;
|
|
||||||
/* 0x0108 */ uint tint_pad_1;
|
|
||||||
/* 0x010c */ int tint_pad_12[1];
|
|
||||||
/* 0x0110 */ float3 tint_pad_3;
|
|
||||||
/* 0x011c */ uint tint_pad_7;
|
|
||||||
/* 0x0120 */ float4 tint_pad_25;
|
|
||||||
/* 0x0130 */ uint tint_pad_5;
|
|
||||||
/* 0x0134 */ int tint_pad_13[1];
|
|
||||||
/* 0x0138 */ float2x2 tint_pad_27;
|
|
||||||
/* 0x0148 */ uint tint_pad_24;
|
|
||||||
/* 0x014c */ int tint_pad_14[1];
|
|
||||||
/* 0x0150 */ float2x3 tint_pad_23;
|
|
||||||
/* 0x0170 */ uint tint_pad_0;
|
|
||||||
/* 0x0174 */ int tint_pad_15[3];
|
|
||||||
/* 0x0180 */ float2x4 tint_pad_8;
|
|
||||||
/* 0x01a0 */ uint tint_pad_26;
|
|
||||||
/* 0x01a4 */ int tint_pad_16[1];
|
|
||||||
/* 0x01a8 */ float3x2 tint_pad_29;
|
|
||||||
/* 0x01c0 */ uint tint_pad_6;
|
|
||||||
/* 0x01c4 */ int tint_pad_17[3];
|
|
||||||
/* 0x01d0 */ float3x3 tint_pad_22;
|
|
||||||
/* 0x0200 */ uint tint_pad_32;
|
|
||||||
/* 0x0204 */ int tint_pad_18[3];
|
|
||||||
/* 0x0210 */ float3x4 tint_pad_34;
|
|
||||||
/* 0x0240 */ uint tint_pad_35;
|
|
||||||
/* 0x0244 */ int tint_pad_19[1];
|
|
||||||
/* 0x0248 */ float4x2 tint_pad_30;
|
|
||||||
/* 0x0268 */ uint tint_pad_9;
|
|
||||||
/* 0x026c */ int tint_pad_36[1];
|
|
||||||
/* 0x0270 */ float4x3 tint_pad_31;
|
|
||||||
/* 0x02b0 */ uint tint_pad_28;
|
|
||||||
/* 0x02b4 */ int tint_pad_37[3];
|
|
||||||
/* 0x02c0 */ float4x4 tint_pad_4;
|
|
||||||
/* 0x0300 */ float tint_pad_21;
|
|
||||||
/* 0x0304 */ int tint_pad_38[31];
|
|
||||||
};
|
|
||||||
|
|
||||||
S make_S(int param_0,
|
|
||||||
float param_1,
|
|
||||||
float2 param_2,
|
|
||||||
uint param_3,
|
|
||||||
float3 param_4,
|
|
||||||
uint param_5,
|
|
||||||
float4 param_6,
|
|
||||||
uint param_7,
|
|
||||||
float2x2 param_8,
|
|
||||||
uint param_9,
|
|
||||||
float2x3 param_10,
|
|
||||||
uint param_11,
|
|
||||||
float2x4 param_12,
|
|
||||||
uint param_13,
|
|
||||||
float3x2 param_14,
|
|
||||||
uint param_15,
|
|
||||||
float3x3 param_16,
|
|
||||||
uint param_17,
|
|
||||||
float3x4 param_18,
|
|
||||||
uint param_19,
|
|
||||||
float4x2 param_20,
|
|
||||||
uint param_21,
|
|
||||||
float4x3 param_22,
|
|
||||||
uint param_23,
|
|
||||||
float4x4 param_24,
|
|
||||||
float param_25) {
|
|
||||||
S output;
|
|
||||||
output.tint_pad_2 = param_0;
|
|
||||||
output.tint_pad_20 = param_1;
|
|
||||||
output.tint_pad_33 = param_2;
|
|
||||||
output.tint_pad_1 = param_3;
|
|
||||||
output.tint_pad_3 = param_4;
|
|
||||||
output.tint_pad_7 = param_5;
|
|
||||||
output.tint_pad_25 = param_6;
|
|
||||||
output.tint_pad_5 = param_7;
|
|
||||||
output.tint_pad_27 = param_8;
|
|
||||||
output.tint_pad_24 = param_9;
|
|
||||||
output.tint_pad_23 = param_10;
|
|
||||||
output.tint_pad_0 = param_11;
|
|
||||||
output.tint_pad_8 = param_12;
|
|
||||||
output.tint_pad_26 = param_13;
|
|
||||||
output.tint_pad_29 = param_14;
|
|
||||||
output.tint_pad_6 = param_15;
|
|
||||||
output.tint_pad_22 = param_16;
|
|
||||||
output.tint_pad_32 = param_17;
|
|
||||||
output.tint_pad_34 = param_18;
|
|
||||||
output.tint_pad_35 = param_19;
|
|
||||||
output.tint_pad_30 = param_20;
|
|
||||||
output.tint_pad_9 = param_21;
|
|
||||||
output.tint_pad_31 = param_22;
|
|
||||||
output.tint_pad_28 = param_23;
|
|
||||||
output.tint_pad_4 = param_24;
|
|
||||||
output.tint_pad_21 = param_25;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
)");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_NameCollision) {
|
TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_NameCollision) {
|
||||||
auto* s = Structure("S", {
|
auto* s = Structure("S", {
|
||||||
Member("double", ty.i32()),
|
Member("double", ty.i32()),
|
||||||
|
|
|
@ -279,7 +279,7 @@ tint_unittests_source_set("tint_unittests_core_src") {
|
||||||
"../src/transform/bound_array_accessors_test.cc",
|
"../src/transform/bound_array_accessors_test.cc",
|
||||||
"../src/transform/calculate_array_length_test.cc",
|
"../src/transform/calculate_array_length_test.cc",
|
||||||
"../src/transform/canonicalize_entry_point_io_test.cc",
|
"../src/transform/canonicalize_entry_point_io_test.cc",
|
||||||
"../src/transform/decompose_storage_access_test.cc",
|
"../src/transform/decompose_memory_access_test.cc",
|
||||||
"../src/transform/external_texture_transform_test.cc",
|
"../src/transform/external_texture_transform_test.cc",
|
||||||
"../src/transform/first_index_offset_test.cc",
|
"../src/transform/first_index_offset_test.cc",
|
||||||
"../src/transform/inline_pointer_lets_test.cc",
|
"../src/transform/inline_pointer_lets_test.cc",
|
||||||
|
|
|
@ -4,40 +4,44 @@ void unused_entry_point() {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tint_padded_array_element {
|
struct tint_padded_array_element {
|
||||||
/* 0x0000 */ int el;
|
int el;
|
||||||
/* 0x0004 */ int tint_pad_0[3];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_padded_array_element make_tint_padded_array_element(int param_0) {
|
|
||||||
tint_padded_array_element output;
|
|
||||||
output.el = param_0;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
struct tint_array_wrapper {
|
struct tint_array_wrapper {
|
||||||
/* 0x0000 */ tint_padded_array_element arr[4];
|
tint_padded_array_element arr[4];
|
||||||
};
|
};
|
||||||
struct S {
|
struct S {
|
||||||
/* 0x0000 */ tint_array_wrapper arr;
|
tint_array_wrapper arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_array_wrapper tint_symbol_2(RWByteAddressBuffer buffer, uint offset) {
|
tint_array_wrapper tint_symbol_2(uint4 buffer[4], uint offset) {
|
||||||
const tint_array_wrapper tint_symbol_3 = {{make_tint_padded_array_element(asint(buffer.Load((offset + 0u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 16u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 32u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 48u))))}};
|
const int scalar_offset = ((offset + 0u)) / 4;
|
||||||
return tint_symbol_3;
|
const int scalar_offset_1 = ((offset + 16u)) / 4;
|
||||||
|
const int scalar_offset_2 = ((offset + 32u)) / 4;
|
||||||
|
const int scalar_offset_3 = ((offset + 48u)) / 4;
|
||||||
|
const tint_array_wrapper tint_symbol_5 = {{{asint(buffer[scalar_offset / 4][scalar_offset % 4])}, {asint(buffer[scalar_offset_1 / 4][scalar_offset_1 % 4])}, {asint(buffer[scalar_offset_2 / 4][scalar_offset_2 % 4])}, {asint(buffer[scalar_offset_3 / 4][scalar_offset_3 % 4])}}};
|
||||||
|
return tint_symbol_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
tint_array_wrapper tint_symbol_4(RWByteAddressBuffer buffer, uint offset) {
|
||||||
|
const tint_array_wrapper tint_symbol_6 = {{{asint(buffer.Load((offset + 0u)))}, {asint(buffer.Load((offset + 16u)))}, {asint(buffer.Load((offset + 32u)))}, {asint(buffer.Load((offset + 48u)))}}};
|
||||||
|
return tint_symbol_6;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tint_array_wrapper src_private;
|
static tint_array_wrapper src_private;
|
||||||
groupshared tint_array_wrapper src_workgroup;
|
groupshared tint_array_wrapper src_workgroup;
|
||||||
ConstantBuffer<S> src_uniform : register(b0, space0);
|
cbuffer cbuffer_src_uniform : register(b0, space0) {
|
||||||
|
uint4 src_uniform[4];
|
||||||
|
};
|
||||||
RWByteAddressBuffer src_storage : register(u1, space0);
|
RWByteAddressBuffer src_storage : register(u1, space0);
|
||||||
|
|
||||||
tint_array_wrapper ret_arr() {
|
tint_array_wrapper ret_arr() {
|
||||||
const tint_array_wrapper tint_symbol_4 = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
const tint_array_wrapper tint_symbol_7 = {{{0}, {0}, {0}, {0}}};
|
||||||
return tint_symbol_4;
|
return tint_symbol_7;
|
||||||
}
|
}
|
||||||
|
|
||||||
S ret_struct_arr() {
|
S ret_struct_arr() {
|
||||||
const S tint_symbol_5 = {{{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}};
|
const S tint_symbol_8 = {{{{0}, {0}, {0}, {0}}}};
|
||||||
return tint_symbol_5;
|
return tint_symbol_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tint_array_wrapper_3 {
|
struct tint_array_wrapper_3 {
|
||||||
|
@ -51,20 +55,20 @@ struct tint_array_wrapper_1 {
|
||||||
};
|
};
|
||||||
|
|
||||||
void foo(tint_array_wrapper src_param) {
|
void foo(tint_array_wrapper src_param) {
|
||||||
tint_array_wrapper src_function = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
tint_array_wrapper src_function = {{{0}, {0}, {0}, {0}}};
|
||||||
tint_array_wrapper tint_symbol = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
tint_array_wrapper tint_symbol = {{{0}, {0}, {0}, {0}}};
|
||||||
const tint_array_wrapper tint_symbol_6 = {{make_tint_padded_array_element(1), make_tint_padded_array_element(2), make_tint_padded_array_element(3), make_tint_padded_array_element(3)}};
|
const tint_array_wrapper tint_symbol_9 = {{{1}, {2}, {3}, {3}}};
|
||||||
tint_symbol = tint_symbol_6;
|
tint_symbol = tint_symbol_9;
|
||||||
tint_symbol = src_param;
|
tint_symbol = src_param;
|
||||||
tint_symbol = ret_arr();
|
tint_symbol = ret_arr();
|
||||||
const tint_array_wrapper src_let = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
const tint_array_wrapper src_let = {{{0}, {0}, {0}, {0}}};
|
||||||
tint_symbol = src_let;
|
tint_symbol = src_let;
|
||||||
tint_symbol = src_function;
|
tint_symbol = src_function;
|
||||||
tint_symbol = src_private;
|
tint_symbol = src_private;
|
||||||
tint_symbol = src_workgroup;
|
tint_symbol = src_workgroup;
|
||||||
tint_symbol = ret_struct_arr().arr;
|
tint_symbol = ret_struct_arr().arr;
|
||||||
tint_symbol = src_uniform.arr;
|
tint_symbol = tint_symbol_2(src_uniform, 0u);
|
||||||
tint_symbol = tint_symbol_2(src_storage, 0u);
|
tint_symbol = tint_symbol_4(src_storage, 0u);
|
||||||
tint_array_wrapper_1 dst_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
tint_array_wrapper_1 dst_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
||||||
tint_array_wrapper_1 src_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
tint_array_wrapper_1 src_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
||||||
dst_nested = src_nested;
|
dst_nested = src_nested;
|
||||||
|
|
|
@ -4,30 +4,34 @@ void unused_entry_point() {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tint_padded_array_element {
|
struct tint_padded_array_element {
|
||||||
/* 0x0000 */ int el;
|
int el;
|
||||||
/* 0x0004 */ int tint_pad_0[3];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_padded_array_element make_tint_padded_array_element(int param_0) {
|
|
||||||
tint_padded_array_element output;
|
|
||||||
output.el = param_0;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
struct tint_array_wrapper {
|
struct tint_array_wrapper {
|
||||||
/* 0x0000 */ tint_padded_array_element arr[4];
|
tint_padded_array_element arr[4];
|
||||||
};
|
};
|
||||||
struct S {
|
struct S {
|
||||||
/* 0x0000 */ tint_array_wrapper arr;
|
tint_array_wrapper arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_array_wrapper tint_symbol_2(RWByteAddressBuffer buffer, uint offset) {
|
tint_array_wrapper tint_symbol_2(uint4 buffer[4], uint offset) {
|
||||||
const tint_array_wrapper tint_symbol_3 = {{make_tint_padded_array_element(asint(buffer.Load((offset + 0u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 16u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 32u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 48u))))}};
|
const int scalar_offset = ((offset + 0u)) / 4;
|
||||||
return tint_symbol_3;
|
const int scalar_offset_1 = ((offset + 16u)) / 4;
|
||||||
|
const int scalar_offset_2 = ((offset + 32u)) / 4;
|
||||||
|
const int scalar_offset_3 = ((offset + 48u)) / 4;
|
||||||
|
const tint_array_wrapper tint_symbol_5 = {{{asint(buffer[scalar_offset / 4][scalar_offset % 4])}, {asint(buffer[scalar_offset_1 / 4][scalar_offset_1 % 4])}, {asint(buffer[scalar_offset_2 / 4][scalar_offset_2 % 4])}, {asint(buffer[scalar_offset_3 / 4][scalar_offset_3 % 4])}}};
|
||||||
|
return tint_symbol_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
tint_array_wrapper tint_symbol_4(RWByteAddressBuffer buffer, uint offset) {
|
||||||
|
const tint_array_wrapper tint_symbol_6 = {{{asint(buffer.Load((offset + 0u)))}, {asint(buffer.Load((offset + 16u)))}, {asint(buffer.Load((offset + 32u)))}, {asint(buffer.Load((offset + 48u)))}}};
|
||||||
|
return tint_symbol_6;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tint_array_wrapper src_private;
|
static tint_array_wrapper src_private;
|
||||||
groupshared tint_array_wrapper src_workgroup;
|
groupshared tint_array_wrapper src_workgroup;
|
||||||
ConstantBuffer<S> src_uniform : register(b0, space0);
|
cbuffer cbuffer_src_uniform : register(b0, space0) {
|
||||||
|
uint4 src_uniform[4];
|
||||||
|
};
|
||||||
RWByteAddressBuffer src_storage : register(u1, space0);
|
RWByteAddressBuffer src_storage : register(u1, space0);
|
||||||
static tint_array_wrapper tint_symbol;
|
static tint_array_wrapper tint_symbol;
|
||||||
|
|
||||||
|
@ -44,29 +48,29 @@ struct tint_array_wrapper_1 {
|
||||||
static tint_array_wrapper_1 dst_nested;
|
static tint_array_wrapper_1 dst_nested;
|
||||||
|
|
||||||
tint_array_wrapper ret_arr() {
|
tint_array_wrapper ret_arr() {
|
||||||
const tint_array_wrapper tint_symbol_4 = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
const tint_array_wrapper tint_symbol_7 = {{{0}, {0}, {0}, {0}}};
|
||||||
return tint_symbol_4;
|
return tint_symbol_7;
|
||||||
}
|
}
|
||||||
|
|
||||||
S ret_struct_arr() {
|
S ret_struct_arr() {
|
||||||
const S tint_symbol_5 = {{{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}};
|
const S tint_symbol_8 = {{{{0}, {0}, {0}, {0}}}};
|
||||||
return tint_symbol_5;
|
return tint_symbol_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void foo(tint_array_wrapper src_param) {
|
void foo(tint_array_wrapper src_param) {
|
||||||
tint_array_wrapper src_function = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
tint_array_wrapper src_function = {{{0}, {0}, {0}, {0}}};
|
||||||
const tint_array_wrapper tint_symbol_6 = {{make_tint_padded_array_element(1), make_tint_padded_array_element(2), make_tint_padded_array_element(3), make_tint_padded_array_element(3)}};
|
const tint_array_wrapper tint_symbol_9 = {{{1}, {2}, {3}, {3}}};
|
||||||
tint_symbol = tint_symbol_6;
|
tint_symbol = tint_symbol_9;
|
||||||
tint_symbol = src_param;
|
tint_symbol = src_param;
|
||||||
tint_symbol = ret_arr();
|
tint_symbol = ret_arr();
|
||||||
const tint_array_wrapper src_let = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
const tint_array_wrapper src_let = {{{0}, {0}, {0}, {0}}};
|
||||||
tint_symbol = src_let;
|
tint_symbol = src_let;
|
||||||
tint_symbol = src_function;
|
tint_symbol = src_function;
|
||||||
tint_symbol = src_private;
|
tint_symbol = src_private;
|
||||||
tint_symbol = src_workgroup;
|
tint_symbol = src_workgroup;
|
||||||
tint_symbol = ret_struct_arr().arr;
|
tint_symbol = ret_struct_arr().arr;
|
||||||
tint_symbol = src_uniform.arr;
|
tint_symbol = tint_symbol_2(src_uniform, 0u);
|
||||||
tint_symbol = tint_symbol_2(src_storage, 0u);
|
tint_symbol = tint_symbol_4(src_storage, 0u);
|
||||||
tint_array_wrapper_1 src_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
tint_array_wrapper_1 src_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
||||||
dst_nested = src_nested;
|
dst_nested = src_nested;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,28 +4,30 @@ void unused_entry_point() {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tint_padded_array_element {
|
struct tint_padded_array_element {
|
||||||
/* 0x0000 */ int el;
|
int el;
|
||||||
/* 0x0004 */ int tint_pad_0[3];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_padded_array_element make_tint_padded_array_element(int param_0) {
|
|
||||||
tint_padded_array_element output;
|
|
||||||
output.el = param_0;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
struct tint_array_wrapper {
|
struct tint_array_wrapper {
|
||||||
/* 0x0000 */ tint_padded_array_element arr[4];
|
tint_padded_array_element arr[4];
|
||||||
};
|
};
|
||||||
struct S {
|
struct S {
|
||||||
/* 0x0000 */ tint_array_wrapper arr;
|
tint_array_wrapper arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_array_wrapper tint_symbol_2(RWByteAddressBuffer buffer, uint offset) {
|
tint_array_wrapper tint_symbol_2(uint4 buffer[4], uint offset) {
|
||||||
const tint_array_wrapper tint_symbol_9 = {{make_tint_padded_array_element(asint(buffer.Load((offset + 0u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 16u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 32u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 48u))))}};
|
const int scalar_offset = ((offset + 0u)) / 4;
|
||||||
return tint_symbol_9;
|
const int scalar_offset_1 = ((offset + 16u)) / 4;
|
||||||
|
const int scalar_offset_2 = ((offset + 32u)) / 4;
|
||||||
|
const int scalar_offset_3 = ((offset + 48u)) / 4;
|
||||||
|
const tint_array_wrapper tint_symbol_11 = {{{asint(buffer[scalar_offset / 4][scalar_offset % 4])}, {asint(buffer[scalar_offset_1 / 4][scalar_offset_1 % 4])}, {asint(buffer[scalar_offset_2 / 4][scalar_offset_2 % 4])}, {asint(buffer[scalar_offset_3 / 4][scalar_offset_3 % 4])}}};
|
||||||
|
return tint_symbol_11;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tint_symbol_4(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper value) {
|
tint_array_wrapper tint_symbol_4(RWByteAddressBuffer buffer, uint offset) {
|
||||||
|
const tint_array_wrapper tint_symbol_12 = {{{asint(buffer.Load((offset + 0u)))}, {asint(buffer.Load((offset + 16u)))}, {asint(buffer.Load((offset + 32u)))}, {asint(buffer.Load((offset + 48u)))}}};
|
||||||
|
return tint_symbol_12;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tint_symbol_6(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper value) {
|
||||||
buffer.Store((offset + 0u), asuint(value.arr[0u].el));
|
buffer.Store((offset + 0u), asuint(value.arr[0u].el));
|
||||||
buffer.Store((offset + 16u), asuint(value.arr[1u].el));
|
buffer.Store((offset + 16u), asuint(value.arr[1u].el));
|
||||||
buffer.Store((offset + 32u), asuint(value.arr[2u].el));
|
buffer.Store((offset + 32u), asuint(value.arr[2u].el));
|
||||||
|
@ -33,64 +35,66 @@ void tint_symbol_4(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper v
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tint_array_wrapper_3 {
|
struct tint_array_wrapper_3 {
|
||||||
/* 0x0000 */ int arr[2];
|
int arr[2];
|
||||||
};
|
};
|
||||||
struct tint_array_wrapper_2 {
|
struct tint_array_wrapper_2 {
|
||||||
/* 0x0000 */ tint_array_wrapper_3 arr[3];
|
tint_array_wrapper_3 arr[3];
|
||||||
};
|
};
|
||||||
struct tint_array_wrapper_1 {
|
struct tint_array_wrapper_1 {
|
||||||
/* 0x0000 */ tint_array_wrapper_2 arr[4];
|
tint_array_wrapper_2 arr[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
void tint_symbol_6(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper_3 value) {
|
void tint_symbol_8(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper_3 value) {
|
||||||
buffer.Store((offset + 0u), asuint(value.arr[0u]));
|
buffer.Store((offset + 0u), asuint(value.arr[0u]));
|
||||||
buffer.Store((offset + 4u), asuint(value.arr[1u]));
|
buffer.Store((offset + 4u), asuint(value.arr[1u]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tint_symbol_7(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper_2 value) {
|
void tint_symbol_9(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper_2 value) {
|
||||||
tint_symbol_6(buffer, (offset + 0u), value.arr[0u]);
|
tint_symbol_8(buffer, (offset + 0u), value.arr[0u]);
|
||||||
tint_symbol_6(buffer, (offset + 8u), value.arr[1u]);
|
tint_symbol_8(buffer, (offset + 8u), value.arr[1u]);
|
||||||
tint_symbol_6(buffer, (offset + 16u), value.arr[2u]);
|
tint_symbol_8(buffer, (offset + 16u), value.arr[2u]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tint_symbol_8(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper_1 value) {
|
void tint_symbol_10(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper_1 value) {
|
||||||
tint_symbol_7(buffer, (offset + 0u), value.arr[0u]);
|
tint_symbol_9(buffer, (offset + 0u), value.arr[0u]);
|
||||||
tint_symbol_7(buffer, (offset + 24u), value.arr[1u]);
|
tint_symbol_9(buffer, (offset + 24u), value.arr[1u]);
|
||||||
tint_symbol_7(buffer, (offset + 48u), value.arr[2u]);
|
tint_symbol_9(buffer, (offset + 48u), value.arr[2u]);
|
||||||
tint_symbol_7(buffer, (offset + 72u), value.arr[3u]);
|
tint_symbol_9(buffer, (offset + 72u), value.arr[3u]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static tint_array_wrapper src_private;
|
static tint_array_wrapper src_private;
|
||||||
groupshared tint_array_wrapper src_workgroup;
|
groupshared tint_array_wrapper src_workgroup;
|
||||||
ConstantBuffer<S> src_uniform : register(b0, space0);
|
cbuffer cbuffer_src_uniform : register(b0, space0) {
|
||||||
|
uint4 src_uniform[4];
|
||||||
|
};
|
||||||
RWByteAddressBuffer src_storage : register(u1, space0);
|
RWByteAddressBuffer src_storage : register(u1, space0);
|
||||||
RWByteAddressBuffer tint_symbol : register(u2, space0);
|
RWByteAddressBuffer tint_symbol : register(u2, space0);
|
||||||
RWByteAddressBuffer dst_nested : register(u3, space0);
|
RWByteAddressBuffer dst_nested : register(u3, space0);
|
||||||
|
|
||||||
tint_array_wrapper ret_arr() {
|
tint_array_wrapper ret_arr() {
|
||||||
const tint_array_wrapper tint_symbol_10 = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
const tint_array_wrapper tint_symbol_13 = {{{0}, {0}, {0}, {0}}};
|
||||||
return tint_symbol_10;
|
return tint_symbol_13;
|
||||||
}
|
}
|
||||||
|
|
||||||
S ret_struct_arr() {
|
S ret_struct_arr() {
|
||||||
const S tint_symbol_11 = {{{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}};
|
const S tint_symbol_14 = {{{{0}, {0}, {0}, {0}}}};
|
||||||
return tint_symbol_11;
|
return tint_symbol_14;
|
||||||
}
|
}
|
||||||
|
|
||||||
void foo(tint_array_wrapper src_param) {
|
void foo(tint_array_wrapper src_param) {
|
||||||
tint_array_wrapper src_function = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
tint_array_wrapper src_function = {{{0}, {0}, {0}, {0}}};
|
||||||
const tint_array_wrapper tint_symbol_12 = {{make_tint_padded_array_element(1), make_tint_padded_array_element(2), make_tint_padded_array_element(3), make_tint_padded_array_element(3)}};
|
const tint_array_wrapper tint_symbol_15 = {{{1}, {2}, {3}, {3}}};
|
||||||
tint_symbol_4(tint_symbol, 0u, tint_symbol_12);
|
tint_symbol_6(tint_symbol, 0u, tint_symbol_15);
|
||||||
tint_symbol_4(tint_symbol, 0u, src_param);
|
tint_symbol_6(tint_symbol, 0u, src_param);
|
||||||
tint_symbol_4(tint_symbol, 0u, ret_arr());
|
tint_symbol_6(tint_symbol, 0u, ret_arr());
|
||||||
const tint_array_wrapper src_let = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
const tint_array_wrapper src_let = {{{0}, {0}, {0}, {0}}};
|
||||||
tint_symbol_4(tint_symbol, 0u, src_let);
|
tint_symbol_6(tint_symbol, 0u, src_let);
|
||||||
tint_symbol_4(tint_symbol, 0u, src_function);
|
tint_symbol_6(tint_symbol, 0u, src_function);
|
||||||
tint_symbol_4(tint_symbol, 0u, src_private);
|
tint_symbol_6(tint_symbol, 0u, src_private);
|
||||||
tint_symbol_4(tint_symbol, 0u, src_workgroup);
|
tint_symbol_6(tint_symbol, 0u, src_workgroup);
|
||||||
tint_symbol_4(tint_symbol, 0u, ret_struct_arr().arr);
|
tint_symbol_6(tint_symbol, 0u, ret_struct_arr().arr);
|
||||||
tint_symbol_4(tint_symbol, 0u, src_uniform.arr);
|
tint_symbol_6(tint_symbol, 0u, tint_symbol_2(src_uniform, 0u));
|
||||||
tint_symbol_4(tint_symbol, 0u, tint_symbol_2(src_storage, 0u));
|
tint_symbol_6(tint_symbol, 0u, tint_symbol_4(src_storage, 0u));
|
||||||
tint_array_wrapper_1 src_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
tint_array_wrapper_1 src_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
||||||
tint_symbol_8(dst_nested, 0u, src_nested);
|
tint_symbol_10(dst_nested, 0u, src_nested);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,30 +4,34 @@ void unused_entry_point() {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tint_padded_array_element {
|
struct tint_padded_array_element {
|
||||||
/* 0x0000 */ int el;
|
int el;
|
||||||
/* 0x0004 */ int tint_pad_0[3];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_padded_array_element make_tint_padded_array_element(int param_0) {
|
|
||||||
tint_padded_array_element output;
|
|
||||||
output.el = param_0;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
struct tint_array_wrapper {
|
struct tint_array_wrapper {
|
||||||
/* 0x0000 */ tint_padded_array_element arr[4];
|
tint_padded_array_element arr[4];
|
||||||
};
|
};
|
||||||
struct S {
|
struct S {
|
||||||
/* 0x0000 */ tint_array_wrapper arr;
|
tint_array_wrapper arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_array_wrapper tint_symbol_2(RWByteAddressBuffer buffer, uint offset) {
|
tint_array_wrapper tint_symbol_2(uint4 buffer[4], uint offset) {
|
||||||
const tint_array_wrapper tint_symbol_3 = {{make_tint_padded_array_element(asint(buffer.Load((offset + 0u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 16u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 32u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 48u))))}};
|
const int scalar_offset = ((offset + 0u)) / 4;
|
||||||
return tint_symbol_3;
|
const int scalar_offset_1 = ((offset + 16u)) / 4;
|
||||||
|
const int scalar_offset_2 = ((offset + 32u)) / 4;
|
||||||
|
const int scalar_offset_3 = ((offset + 48u)) / 4;
|
||||||
|
const tint_array_wrapper tint_symbol_5 = {{{asint(buffer[scalar_offset / 4][scalar_offset % 4])}, {asint(buffer[scalar_offset_1 / 4][scalar_offset_1 % 4])}, {asint(buffer[scalar_offset_2 / 4][scalar_offset_2 % 4])}, {asint(buffer[scalar_offset_3 / 4][scalar_offset_3 % 4])}}};
|
||||||
|
return tint_symbol_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
tint_array_wrapper tint_symbol_4(RWByteAddressBuffer buffer, uint offset) {
|
||||||
|
const tint_array_wrapper tint_symbol_6 = {{{asint(buffer.Load((offset + 0u)))}, {asint(buffer.Load((offset + 16u)))}, {asint(buffer.Load((offset + 32u)))}, {asint(buffer.Load((offset + 48u)))}}};
|
||||||
|
return tint_symbol_6;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tint_array_wrapper src_private;
|
static tint_array_wrapper src_private;
|
||||||
groupshared tint_array_wrapper src_workgroup;
|
groupshared tint_array_wrapper src_workgroup;
|
||||||
ConstantBuffer<S> src_uniform : register(b0, space0);
|
cbuffer cbuffer_src_uniform : register(b0, space0) {
|
||||||
|
uint4 src_uniform[4];
|
||||||
|
};
|
||||||
RWByteAddressBuffer src_storage : register(u1, space0);
|
RWByteAddressBuffer src_storage : register(u1, space0);
|
||||||
groupshared tint_array_wrapper tint_symbol;
|
groupshared tint_array_wrapper tint_symbol;
|
||||||
|
|
||||||
|
@ -44,29 +48,29 @@ struct tint_array_wrapper_1 {
|
||||||
groupshared tint_array_wrapper_1 dst_nested;
|
groupshared tint_array_wrapper_1 dst_nested;
|
||||||
|
|
||||||
tint_array_wrapper ret_arr() {
|
tint_array_wrapper ret_arr() {
|
||||||
const tint_array_wrapper tint_symbol_4 = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
const tint_array_wrapper tint_symbol_7 = {{{0}, {0}, {0}, {0}}};
|
||||||
return tint_symbol_4;
|
return tint_symbol_7;
|
||||||
}
|
}
|
||||||
|
|
||||||
S ret_struct_arr() {
|
S ret_struct_arr() {
|
||||||
const S tint_symbol_5 = {{{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}};
|
const S tint_symbol_8 = {{{{0}, {0}, {0}, {0}}}};
|
||||||
return tint_symbol_5;
|
return tint_symbol_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void foo(tint_array_wrapper src_param) {
|
void foo(tint_array_wrapper src_param) {
|
||||||
tint_array_wrapper src_function = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
tint_array_wrapper src_function = {{{0}, {0}, {0}, {0}}};
|
||||||
const tint_array_wrapper tint_symbol_6 = {{make_tint_padded_array_element(1), make_tint_padded_array_element(2), make_tint_padded_array_element(3), make_tint_padded_array_element(3)}};
|
const tint_array_wrapper tint_symbol_9 = {{{1}, {2}, {3}, {3}}};
|
||||||
tint_symbol = tint_symbol_6;
|
tint_symbol = tint_symbol_9;
|
||||||
tint_symbol = src_param;
|
tint_symbol = src_param;
|
||||||
tint_symbol = ret_arr();
|
tint_symbol = ret_arr();
|
||||||
const tint_array_wrapper src_let = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}};
|
const tint_array_wrapper src_let = {{{0}, {0}, {0}, {0}}};
|
||||||
tint_symbol = src_let;
|
tint_symbol = src_let;
|
||||||
tint_symbol = src_function;
|
tint_symbol = src_function;
|
||||||
tint_symbol = src_private;
|
tint_symbol = src_private;
|
||||||
tint_symbol = src_workgroup;
|
tint_symbol = src_workgroup;
|
||||||
tint_symbol = ret_struct_arr().arr;
|
tint_symbol = ret_struct_arr().arr;
|
||||||
tint_symbol = src_uniform.arr;
|
tint_symbol = tint_symbol_2(src_uniform, 0u);
|
||||||
tint_symbol = tint_symbol_2(src_storage, 0u);
|
tint_symbol = tint_symbol_4(src_storage, 0u);
|
||||||
tint_array_wrapper_1 src_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
tint_array_wrapper_1 src_nested = {{{{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}, {{{{0, 0}}, {{0, 0}}, {{0, 0}}}}}};
|
||||||
dst_nested = src_nested;
|
dst_nested = src_nested;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
struct Uniforms {
|
|
||||||
/* 0x0000 */ uint2 aShape;
|
|
||||||
/* 0x0008 */ uint2 bShape;
|
|
||||||
/* 0x0010 */ uint2 outShape;
|
|
||||||
};
|
|
||||||
|
|
||||||
ByteAddressBuffer firstMatrix : register(t0, space0);
|
ByteAddressBuffer firstMatrix : register(t0, space0);
|
||||||
ByteAddressBuffer secondMatrix : register(t1, space0);
|
ByteAddressBuffer secondMatrix : register(t1, space0);
|
||||||
RWByteAddressBuffer resultMatrix : register(u2, space0);
|
RWByteAddressBuffer resultMatrix : register(u2, space0);
|
||||||
ConstantBuffer<Uniforms> uniforms : register(b3, space0);
|
cbuffer cbuffer_uniforms : register(b3, space0) {
|
||||||
|
uint4 uniforms[2];
|
||||||
|
};
|
||||||
|
|
||||||
struct tint_symbol_1 {
|
struct tint_symbol_1 {
|
||||||
uint3 global_id : SV_DispatchThreadID;
|
uint3 global_id : SV_DispatchThreadID;
|
||||||
|
@ -17,8 +13,10 @@ struct tint_symbol_1 {
|
||||||
void main(tint_symbol_1 tint_symbol) {
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
const uint3 global_id = tint_symbol.global_id;
|
const uint3 global_id = tint_symbol.global_id;
|
||||||
const uint2 resultCell = uint2(global_id.y, global_id.x);
|
const uint2 resultCell = uint2(global_id.y, global_id.x);
|
||||||
const uint dimInner = uniforms.aShape.y;
|
const int scalar_offset = (4u) / 4;
|
||||||
const uint dimOutter = uniforms.outShape.y;
|
const uint dimInner = uniforms[scalar_offset / 4][scalar_offset % 4];
|
||||||
|
const int scalar_offset_1 = (20u) / 4;
|
||||||
|
const uint dimOutter = uniforms[scalar_offset_1 / 4][scalar_offset_1 % 4];
|
||||||
uint result = 0u;
|
uint result = 0u;
|
||||||
{
|
{
|
||||||
uint i = 0u;
|
uint i = 0u;
|
||||||
|
|
|
@ -4,13 +4,12 @@ struct tint_array_wrapper {
|
||||||
struct QuicksortObject {
|
struct QuicksortObject {
|
||||||
tint_array_wrapper numbers;
|
tint_array_wrapper numbers;
|
||||||
};
|
};
|
||||||
struct buf0 {
|
|
||||||
/* 0x0000 */ float2 resolution;
|
|
||||||
};
|
|
||||||
|
|
||||||
static QuicksortObject obj;
|
static QuicksortObject obj;
|
||||||
static float4 gl_FragCoord;
|
static float4 gl_FragCoord;
|
||||||
ConstantBuffer<buf0> x_188 : register(b0, space0);
|
cbuffer cbuffer_x_188 : register(b0, space0) {
|
||||||
|
uint4 x_188[1];
|
||||||
|
};
|
||||||
static float4 x_GLF_color;
|
static float4 x_GLF_color;
|
||||||
|
|
||||||
void swap_i1_i1_(inout int i, inout int j) {
|
void swap_i1_i1_(inout int i, inout int j) {
|
||||||
|
@ -61,18 +60,18 @@ void swap_i1_i1_(inout int i, inout int j) {
|
||||||
const int x_34_save = x_33;
|
const int x_34_save = x_33;
|
||||||
const int x_35 = obj.numbers.arr[x_34_save];
|
const int x_35 = obj.numbers.arr[x_34_save];
|
||||||
const QuicksortObject x_943 = obj;
|
const QuicksortObject x_943 = obj;
|
||||||
const tint_array_wrapper tint_symbol_4 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_5 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_5 = {tint_symbol_4};
|
const QuicksortObject tint_symbol_6 = {tint_symbol_5};
|
||||||
obj = tint_symbol_5;
|
obj = tint_symbol_6;
|
||||||
obj = x_943;
|
obj = x_943;
|
||||||
const float2 x_527 = float2(x_526.x, x_526.x);
|
const float2 x_527 = float2(x_526.x, x_526.x);
|
||||||
const int x_36_save = x_32;
|
const int x_36_save = x_32;
|
||||||
const float3 x_528 = float3(x_524.x, x_524.z, x_524.x);
|
const float3 x_528 = float3(x_524.x, x_524.z, x_524.x);
|
||||||
obj.numbers.arr[x_36_save] = x_35;
|
obj.numbers.arr[x_36_save] = x_35;
|
||||||
const QuicksortObject x_944 = obj;
|
const QuicksortObject x_944 = obj;
|
||||||
const tint_array_wrapper tint_symbol_6 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_7 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_7 = {tint_symbol_6};
|
const QuicksortObject tint_symbol_8 = {tint_symbol_7};
|
||||||
obj = tint_symbol_7;
|
obj = tint_symbol_8;
|
||||||
obj = x_944;
|
obj = x_944;
|
||||||
const float3 x_529 = float3(x_526.y, x_526.z, x_526.x);
|
const float3 x_529 = float3(x_526.y, x_526.z, x_526.x);
|
||||||
const int x_945 = i;
|
const int x_945 = i;
|
||||||
|
@ -95,9 +94,9 @@ void swap_i1_i1_(inout int i, inout int j) {
|
||||||
obj.numbers.arr[x_36_save] = 0;
|
obj.numbers.arr[x_36_save] = 0;
|
||||||
obj.numbers.arr[x_36_save] = x_949;
|
obj.numbers.arr[x_36_save] = x_949;
|
||||||
const QuicksortObject x_950 = obj;
|
const QuicksortObject x_950 = obj;
|
||||||
const tint_array_wrapper tint_symbol_8 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_9 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_9 = {tint_symbol_8};
|
const QuicksortObject tint_symbol_10 = {tint_symbol_9};
|
||||||
obj = tint_symbol_9;
|
obj = tint_symbol_10;
|
||||||
obj = x_950;
|
obj = x_950;
|
||||||
const float3 x_532 = float3(x_528.x, x_528.y, x_528.x);
|
const float3 x_532 = float3(x_528.x, x_528.y, x_528.x);
|
||||||
const int x_951 = obj.numbers.arr[x_34_save];
|
const int x_951 = obj.numbers.arr[x_34_save];
|
||||||
|
@ -153,9 +152,9 @@ int performPartition_i1_i1_(inout int l, inout int h) {
|
||||||
const float3 x_536 = float3(x_534.x, x_534.z, x_535.x);
|
const float3 x_536 = float3(x_534.x, x_534.z, x_535.x);
|
||||||
j_1 = 10;
|
j_1 = 10;
|
||||||
const QuicksortObject x_960 = obj;
|
const QuicksortObject x_960 = obj;
|
||||||
const tint_array_wrapper tint_symbol_10 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_11 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_11 = {tint_symbol_10};
|
const QuicksortObject tint_symbol_12 = {tint_symbol_11};
|
||||||
obj = tint_symbol_11;
|
obj = tint_symbol_12;
|
||||||
obj = x_960;
|
obj = x_960;
|
||||||
while (true) {
|
while (true) {
|
||||||
const int x_961 = pivot;
|
const int x_961 = pivot;
|
||||||
|
@ -170,9 +169,9 @@ int performPartition_i1_i1_(inout int l, inout int h) {
|
||||||
pivot = x_963;
|
pivot = x_963;
|
||||||
x_537 = float2(float3(1.0f, 2.0f, 3.0f).y, float3(1.0f, 2.0f, 3.0f).z);
|
x_537 = float2(float3(1.0f, 2.0f, 3.0f).y, float3(1.0f, 2.0f, 3.0f).z);
|
||||||
const QuicksortObject x_964 = obj;
|
const QuicksortObject x_964 = obj;
|
||||||
const tint_array_wrapper tint_symbol_12 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_13 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_13 = {tint_symbol_12};
|
const QuicksortObject tint_symbol_14 = {tint_symbol_13};
|
||||||
obj = tint_symbol_13;
|
obj = tint_symbol_14;
|
||||||
obj = x_964;
|
obj = x_964;
|
||||||
const int x_56 = h;
|
const int x_56 = h;
|
||||||
const int x_965 = h;
|
const int x_965 = h;
|
||||||
|
@ -206,9 +205,9 @@ int performPartition_i1_i1_(inout int l, inout int h) {
|
||||||
param_1 = x_971;
|
param_1 = x_971;
|
||||||
const int x_62 = obj.numbers.arr[x_61_save];
|
const int x_62 = obj.numbers.arr[x_61_save];
|
||||||
const QuicksortObject x_972 = obj;
|
const QuicksortObject x_972 = obj;
|
||||||
const tint_array_wrapper tint_symbol_14 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_15 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_15 = {tint_symbol_14};
|
const QuicksortObject tint_symbol_16 = {tint_symbol_15};
|
||||||
obj = tint_symbol_15;
|
obj = tint_symbol_16;
|
||||||
obj = x_972;
|
obj = x_972;
|
||||||
const int x_63 = pivot;
|
const int x_63 = pivot;
|
||||||
const float2 x_540 = float2(float3(1.0f, 2.0f, 3.0f).y, x_534.z);
|
const float2 x_540 = float2(float3(1.0f, 2.0f, 3.0f).y, x_534.z);
|
||||||
|
@ -267,9 +266,9 @@ int performPartition_i1_i1_(inout int l, inout int h) {
|
||||||
param_1 = x_985;
|
param_1 = x_985;
|
||||||
}
|
}
|
||||||
const QuicksortObject x_986 = obj;
|
const QuicksortObject x_986 = obj;
|
||||||
const tint_array_wrapper tint_symbol_16 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_17 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_17 = {tint_symbol_16};
|
const QuicksortObject tint_symbol_18 = {tint_symbol_17};
|
||||||
obj = tint_symbol_17;
|
obj = tint_symbol_18;
|
||||||
obj = x_986;
|
obj = x_986;
|
||||||
{
|
{
|
||||||
const int x_987 = h;
|
const int x_987 = h;
|
||||||
|
@ -302,9 +301,9 @@ int performPartition_i1_i1_(inout int l, inout int h) {
|
||||||
obj.numbers.arr[x_42_save] = x_993;
|
obj.numbers.arr[x_42_save] = x_993;
|
||||||
const float2 x_549 = float2(x_534.x, x_534.y);
|
const float2 x_549 = float2(x_534.x, x_534.y);
|
||||||
const QuicksortObject x_994 = obj;
|
const QuicksortObject x_994 = obj;
|
||||||
const tint_array_wrapper tint_symbol_18 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_19 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_19 = {tint_symbol_18};
|
const QuicksortObject tint_symbol_20 = {tint_symbol_19};
|
||||||
obj = tint_symbol_19;
|
obj = tint_symbol_20;
|
||||||
obj = x_994;
|
obj = x_994;
|
||||||
const int x_995 = h;
|
const int x_995 = h;
|
||||||
h = 0;
|
h = 0;
|
||||||
|
@ -372,8 +371,8 @@ void quicksort_() {
|
||||||
param_5 = x_1007;
|
param_5 = x_1007;
|
||||||
h_1 = 9;
|
h_1 = 9;
|
||||||
const tint_array_wrapper x_1008 = stack;
|
const tint_array_wrapper x_1008 = stack;
|
||||||
const tint_array_wrapper tint_symbol_20 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_21 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_20;
|
stack = tint_symbol_21;
|
||||||
stack = x_1008;
|
stack = x_1008;
|
||||||
const float2 x_556 = float2(float3(1.0f, 2.0f, 3.0f).y, float3(1.0f, 2.0f, 3.0f).y);
|
const float2 x_556 = float2(float3(1.0f, 2.0f, 3.0f).y, float3(1.0f, 2.0f, 3.0f).y);
|
||||||
const int x_1009 = param_5;
|
const int x_1009 = param_5;
|
||||||
|
@ -406,15 +405,15 @@ void quicksort_() {
|
||||||
param_4 = x_1015;
|
param_4 = x_1015;
|
||||||
const int x_95 = l_1;
|
const int x_95 = l_1;
|
||||||
const QuicksortObject x_1016 = obj;
|
const QuicksortObject x_1016 = obj;
|
||||||
const tint_array_wrapper tint_symbol_21 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_22 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_22 = {tint_symbol_21};
|
const QuicksortObject tint_symbol_23 = {tint_symbol_22};
|
||||||
obj = tint_symbol_22;
|
obj = tint_symbol_23;
|
||||||
obj = x_1016;
|
obj = x_1016;
|
||||||
const float3 x_560 = float3(x_559.y, x_559.x, x_557.x);
|
const float3 x_560 = float3(x_559.y, x_559.x, x_557.x);
|
||||||
const int x_96_save = x_94;
|
const int x_96_save = x_94;
|
||||||
const tint_array_wrapper x_1017 = stack;
|
const tint_array_wrapper x_1017 = stack;
|
||||||
const tint_array_wrapper tint_symbol_23 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_24 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_23;
|
stack = tint_symbol_24;
|
||||||
stack = x_1017;
|
stack = x_1017;
|
||||||
const float3 x_561 = float3(x_556.y, x_556.y, x_556.y);
|
const float3 x_561 = float3(x_556.y, x_556.y, x_556.y);
|
||||||
const int x_1018 = l_1;
|
const int x_1018 = l_1;
|
||||||
|
@ -464,13 +463,13 @@ void quicksort_() {
|
||||||
h_1 = 0;
|
h_1 = 0;
|
||||||
h_1 = x_1028;
|
h_1 = x_1028;
|
||||||
const tint_array_wrapper x_1029 = stack;
|
const tint_array_wrapper x_1029 = stack;
|
||||||
const tint_array_wrapper tint_symbol_24 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_25 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_24;
|
stack = tint_symbol_25;
|
||||||
stack = x_1029;
|
stack = x_1029;
|
||||||
const int x_106 = top;
|
const int x_106 = top;
|
||||||
const tint_array_wrapper x_1030 = stack;
|
const tint_array_wrapper x_1030 = stack;
|
||||||
const tint_array_wrapper tint_symbol_25 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_26 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_25;
|
stack = tint_symbol_26;
|
||||||
stack = x_1030;
|
stack = x_1030;
|
||||||
const float2 x_567 = float2(x_558.x, x_564.z);
|
const float2 x_567 = float2(x_558.x, x_564.z);
|
||||||
const int x_1031 = param_4;
|
const int x_1031 = param_4;
|
||||||
|
@ -481,9 +480,9 @@ void quicksort_() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const QuicksortObject x_1032 = obj;
|
const QuicksortObject x_1032 = obj;
|
||||||
const tint_array_wrapper tint_symbol_26 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_27 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_27 = {tint_symbol_26};
|
const QuicksortObject tint_symbol_28 = {tint_symbol_27};
|
||||||
obj = tint_symbol_27;
|
obj = tint_symbol_28;
|
||||||
obj = x_1032;
|
obj = x_1032;
|
||||||
const float3 x_568 = float3(x_559.y, x_559.x, x_563.y);
|
const float3 x_568 = float3(x_559.y, x_559.x, x_563.y);
|
||||||
const int x_1033 = param_4;
|
const int x_1033 = param_4;
|
||||||
|
@ -508,8 +507,8 @@ void quicksort_() {
|
||||||
stack.arr[x_96_save] = x_1037;
|
stack.arr[x_96_save] = x_1037;
|
||||||
const int x_111 = stack.arr[x_110_save];
|
const int x_111 = stack.arr[x_110_save];
|
||||||
const tint_array_wrapper x_1038 = stack;
|
const tint_array_wrapper x_1038 = stack;
|
||||||
const tint_array_wrapper tint_symbol_28 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_29 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_28;
|
stack = tint_symbol_29;
|
||||||
stack = x_1038;
|
stack = x_1038;
|
||||||
const float3 x_571 = float3(x_559.y, x_559.x, x_564.y);
|
const float3 x_571 = float3(x_559.y, x_559.x, x_564.y);
|
||||||
const int x_1039 = l_1;
|
const int x_1039 = l_1;
|
||||||
|
@ -517,8 +516,8 @@ void quicksort_() {
|
||||||
l_1 = x_1039;
|
l_1 = x_1039;
|
||||||
h_1 = x_111;
|
h_1 = x_111;
|
||||||
const tint_array_wrapper x_1040 = stack;
|
const tint_array_wrapper x_1040 = stack;
|
||||||
const tint_array_wrapper tint_symbol_29 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_30 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_29;
|
stack = tint_symbol_30;
|
||||||
stack = x_1040;
|
stack = x_1040;
|
||||||
const float2 x_572 = float2(x_562.y, x_561.y);
|
const float2 x_572 = float2(x_562.y, x_561.y);
|
||||||
const int x_1041 = p;
|
const int x_1041 = p;
|
||||||
|
@ -610,8 +609,8 @@ void quicksort_() {
|
||||||
stack.arr[x_100_save] = 0;
|
stack.arr[x_100_save] = 0;
|
||||||
stack.arr[x_100_save] = x_1061;
|
stack.arr[x_100_save] = x_1061;
|
||||||
const tint_array_wrapper x_1062 = stack;
|
const tint_array_wrapper x_1062 = stack;
|
||||||
const tint_array_wrapper tint_symbol_30 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_31 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_30;
|
stack = tint_symbol_31;
|
||||||
stack = x_1062;
|
stack = x_1062;
|
||||||
const float2 x_584 = float2(x_569.z, x_569.y);
|
const float2 x_584 = float2(x_569.z, x_569.y);
|
||||||
const float3 x_585 = float3(x_580.y, x_577.x, x_577.x);
|
const float3 x_585 = float3(x_580.y, x_577.x, x_577.x);
|
||||||
|
@ -650,8 +649,8 @@ void quicksort_() {
|
||||||
h_1 = x_1070;
|
h_1 = x_1070;
|
||||||
top = x_133;
|
top = x_133;
|
||||||
const tint_array_wrapper x_1071 = stack;
|
const tint_array_wrapper x_1071 = stack;
|
||||||
const tint_array_wrapper tint_symbol_31 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_32 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_31;
|
stack = tint_symbol_32;
|
||||||
stack = x_1071;
|
stack = x_1071;
|
||||||
const int x_134 = p;
|
const int x_134 = p;
|
||||||
const float2 x_590 = float2(x_576.x, x_573.y);
|
const float2 x_590 = float2(x_576.x, x_573.y);
|
||||||
|
@ -676,9 +675,9 @@ void quicksort_() {
|
||||||
stack.arr[x_96_save] = x_1076;
|
stack.arr[x_96_save] = x_1076;
|
||||||
const float2 x_592 = float2(float3(1.0f, 2.0f, 3.0f).x, float3(1.0f, 2.0f, 3.0f).y);
|
const float2 x_592 = float2(float3(1.0f, 2.0f, 3.0f).x, float3(1.0f, 2.0f, 3.0f).y);
|
||||||
const QuicksortObject x_1077 = obj;
|
const QuicksortObject x_1077 = obj;
|
||||||
const tint_array_wrapper tint_symbol_32 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_33 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_33 = {tint_symbol_32};
|
const QuicksortObject tint_symbol_34 = {tint_symbol_33};
|
||||||
obj = tint_symbol_33;
|
obj = tint_symbol_34;
|
||||||
obj = x_1077;
|
obj = x_1077;
|
||||||
const int x_137 = p;
|
const int x_137 = p;
|
||||||
const int x_1078 = stack.arr[x_114_save];
|
const int x_1078 = stack.arr[x_114_save];
|
||||||
|
@ -743,8 +742,8 @@ void quicksort_() {
|
||||||
const float2 x_601 = float2(x_563.x, x_563.y);
|
const float2 x_601 = float2(x_563.x, x_563.y);
|
||||||
stack.arr[x_147_save] = asint((1u + asuint(x_145)));
|
stack.arr[x_147_save] = asint((1u + asuint(x_145)));
|
||||||
const tint_array_wrapper x_1093 = stack;
|
const tint_array_wrapper x_1093 = stack;
|
||||||
const tint_array_wrapper tint_symbol_34 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_35 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_34;
|
stack = tint_symbol_35;
|
||||||
stack = x_1093;
|
stack = x_1093;
|
||||||
const int x_148 = top;
|
const int x_148 = top;
|
||||||
const int x_1094 = stack.arr[x_114_save];
|
const int x_1094 = stack.arr[x_114_save];
|
||||||
|
@ -752,8 +751,8 @@ void quicksort_() {
|
||||||
stack.arr[x_114_save] = x_1094;
|
stack.arr[x_114_save] = x_1094;
|
||||||
const float2 x_602 = float2(x_565.y, x_599.y);
|
const float2 x_602 = float2(x_565.y, x_599.y);
|
||||||
const tint_array_wrapper x_1095 = stack;
|
const tint_array_wrapper x_1095 = stack;
|
||||||
const tint_array_wrapper tint_symbol_35 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_36 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
stack = tint_symbol_35;
|
stack = tint_symbol_36;
|
||||||
stack = x_1095;
|
stack = x_1095;
|
||||||
const int x_149 = (x_148 + asint(1u));
|
const int x_149 = (x_148 + asint(1u));
|
||||||
const int x_1096 = stack.arr[x_147_save];
|
const int x_1096 = stack.arr[x_147_save];
|
||||||
|
@ -788,9 +787,9 @@ void quicksort_() {
|
||||||
l_1 = x_1103;
|
l_1 = x_1103;
|
||||||
const float2 x_604 = float2(x_563.z, x_564.x);
|
const float2 x_604 = float2(x_563.z, x_564.x);
|
||||||
const QuicksortObject x_1104 = obj;
|
const QuicksortObject x_1104 = obj;
|
||||||
const tint_array_wrapper tint_symbol_36 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_37 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_37 = {tint_symbol_36};
|
const QuicksortObject tint_symbol_38 = {tint_symbol_37};
|
||||||
obj = tint_symbol_37;
|
obj = tint_symbol_38;
|
||||||
obj = x_1104;
|
obj = x_1104;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,15 +808,15 @@ void main_1() {
|
||||||
uv = x_717;
|
uv = x_717;
|
||||||
i_2 = 0;
|
i_2 = 0;
|
||||||
const QuicksortObject x_721 = obj;
|
const QuicksortObject x_721 = obj;
|
||||||
const tint_array_wrapper tint_symbol_38 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_39 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_39 = {tint_symbol_38};
|
const QuicksortObject tint_symbol_40 = {tint_symbol_39};
|
||||||
obj = tint_symbol_39;
|
obj = tint_symbol_40;
|
||||||
obj = x_721;
|
obj = x_721;
|
||||||
if (true) {
|
if (true) {
|
||||||
const QuicksortObject x_722 = obj;
|
const QuicksortObject x_722 = obj;
|
||||||
const tint_array_wrapper tint_symbol_40 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_41 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_41 = {tint_symbol_40};
|
const QuicksortObject tint_symbol_42 = {tint_symbol_41};
|
||||||
obj = tint_symbol_41;
|
obj = tint_symbol_42;
|
||||||
obj = x_722;
|
obj = x_722;
|
||||||
const float2 x_431 = float2(float3(1.0f, 2.0f, 3.0f).x, float3(1.0f, 2.0f, 3.0f).x);
|
const float2 x_431 = float2(float3(1.0f, 2.0f, 3.0f).x, float3(1.0f, 2.0f, 3.0f).x);
|
||||||
const int x_158 = i_2;
|
const int x_158 = i_2;
|
||||||
|
@ -829,15 +828,15 @@ void main_1() {
|
||||||
color = x_725;
|
color = x_725;
|
||||||
const float2 x_432 = float2(x_431.y, x_431.y);
|
const float2 x_432 = float2(x_431.y, x_431.y);
|
||||||
const QuicksortObject x_726 = obj;
|
const QuicksortObject x_726 = obj;
|
||||||
const tint_array_wrapper tint_symbol_42 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_43 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_43 = {tint_symbol_42};
|
const QuicksortObject tint_symbol_44 = {tint_symbol_43};
|
||||||
obj = tint_symbol_43;
|
obj = tint_symbol_44;
|
||||||
obj = x_726;
|
obj = x_726;
|
||||||
}
|
}
|
||||||
const QuicksortObject x_756 = obj;
|
const QuicksortObject x_756 = obj;
|
||||||
const tint_array_wrapper tint_symbol_44 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_45 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_45 = {tint_symbol_44};
|
const QuicksortObject tint_symbol_46 = {tint_symbol_45};
|
||||||
obj = tint_symbol_45;
|
obj = tint_symbol_46;
|
||||||
obj = x_756;
|
obj = x_756;
|
||||||
const float2 x_446 = float2(float2(0.0f, 0.0f).x, float2(0.0f, 0.0f).x);
|
const float2 x_446 = float2(float2(0.0f, 0.0f).x, float2(0.0f, 0.0f).x);
|
||||||
const int x_757 = i_2;
|
const int x_757 = i_2;
|
||||||
|
@ -845,9 +844,9 @@ void main_1() {
|
||||||
i_2 = x_757;
|
i_2 = x_757;
|
||||||
quicksort_();
|
quicksort_();
|
||||||
const QuicksortObject x_758 = obj;
|
const QuicksortObject x_758 = obj;
|
||||||
const tint_array_wrapper tint_symbol_46 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_47 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_47 = {tint_symbol_46};
|
const QuicksortObject tint_symbol_48 = {tint_symbol_47};
|
||||||
obj = tint_symbol_47;
|
obj = tint_symbol_48;
|
||||||
obj = x_758;
|
obj = x_758;
|
||||||
const float4 x_184 = gl_FragCoord;
|
const float4 x_184 = gl_FragCoord;
|
||||||
const float2 x_759 = uv;
|
const float2 x_759 = uv;
|
||||||
|
@ -860,18 +859,20 @@ void main_1() {
|
||||||
const float2 x_185 = float2(x_184.x, x_184.y);
|
const float2 x_185 = float2(x_184.x, x_184.y);
|
||||||
const float3 x_448 = float3(x_185.y, x_446.y, x_446.y);
|
const float3 x_448 = float3(x_185.y, x_446.y, x_446.y);
|
||||||
const QuicksortObject x_761 = obj;
|
const QuicksortObject x_761 = obj;
|
||||||
const tint_array_wrapper tint_symbol_48 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_49 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_49 = {tint_symbol_48};
|
const QuicksortObject tint_symbol_50 = {tint_symbol_49};
|
||||||
obj = tint_symbol_49;
|
obj = tint_symbol_50;
|
||||||
obj = x_761;
|
obj = x_761;
|
||||||
const float2 x_762 = uv;
|
const float2 x_762 = uv;
|
||||||
uv = float2(0.0f, 0.0f);
|
uv = float2(0.0f, 0.0f);
|
||||||
uv = x_762;
|
uv = x_762;
|
||||||
const float2 x_191 = x_188.resolution;
|
const int scalar_offset = (0u) / 4;
|
||||||
|
uint4 ubo_load = x_188[scalar_offset / 4];
|
||||||
|
const float2 x_191 = asfloat((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy);
|
||||||
const QuicksortObject x_763 = obj;
|
const QuicksortObject x_763 = obj;
|
||||||
const tint_array_wrapper tint_symbol_50 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_51 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_51 = {tint_symbol_50};
|
const QuicksortObject tint_symbol_52 = {tint_symbol_51};
|
||||||
obj = tint_symbol_51;
|
obj = tint_symbol_52;
|
||||||
obj = x_763;
|
obj = x_763;
|
||||||
const float3 x_449 = float3(x_184.y, float3(1.0f, 2.0f, 3.0f).z, x_184.w);
|
const float3 x_449 = float3(x_184.y, float3(1.0f, 2.0f, 3.0f).z, x_184.w);
|
||||||
const float3 x_764 = color;
|
const float3 x_764 = color;
|
||||||
|
@ -879,9 +880,9 @@ void main_1() {
|
||||||
color = x_764;
|
color = x_764;
|
||||||
const float2 x_192 = (x_185 / x_191);
|
const float2 x_192 = (x_185 / x_191);
|
||||||
const QuicksortObject x_765 = obj;
|
const QuicksortObject x_765 = obj;
|
||||||
const tint_array_wrapper tint_symbol_52 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_53 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_53 = {tint_symbol_52};
|
const QuicksortObject tint_symbol_54 = {tint_symbol_53};
|
||||||
obj = tint_symbol_53;
|
obj = tint_symbol_54;
|
||||||
obj = x_765;
|
obj = x_765;
|
||||||
const float2 x_450 = float2(x_447.x, x_185.y);
|
const float2 x_450 = float2(x_447.x, x_185.y);
|
||||||
const float3 x_766 = color;
|
const float3 x_766 = color;
|
||||||
|
@ -897,18 +898,18 @@ void main_1() {
|
||||||
color = x_768;
|
color = x_768;
|
||||||
const float3 x_451 = float3(x_185.x, x_185.y, x_446.y);
|
const float3 x_451 = float3(x_185.x, x_185.y, x_446.y);
|
||||||
const QuicksortObject x_769 = obj;
|
const QuicksortObject x_769 = obj;
|
||||||
const tint_array_wrapper tint_symbol_54 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_55 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_55 = {tint_symbol_54};
|
const QuicksortObject tint_symbol_56 = {tint_symbol_55};
|
||||||
obj = tint_symbol_55;
|
obj = tint_symbol_56;
|
||||||
obj = x_769;
|
obj = x_769;
|
||||||
const int x_770 = obj.numbers.arr[0u];
|
const int x_770 = obj.numbers.arr[0u];
|
||||||
obj.numbers.arr[0u] = 0;
|
obj.numbers.arr[0u] = 0;
|
||||||
obj.numbers.arr[0u] = x_770;
|
obj.numbers.arr[0u] = x_770;
|
||||||
const int x_201 = obj.numbers.arr[0u];
|
const int x_201 = obj.numbers.arr[0u];
|
||||||
const QuicksortObject x_771 = obj;
|
const QuicksortObject x_771 = obj;
|
||||||
const tint_array_wrapper tint_symbol_56 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_57 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_57 = {tint_symbol_56};
|
const QuicksortObject tint_symbol_58 = {tint_symbol_57};
|
||||||
obj = tint_symbol_57;
|
obj = tint_symbol_58;
|
||||||
obj = x_771;
|
obj = x_771;
|
||||||
const int x_772 = obj.numbers.arr[0u];
|
const int x_772 = obj.numbers.arr[0u];
|
||||||
obj.numbers.arr[0u] = 0;
|
obj.numbers.arr[0u] = 0;
|
||||||
|
@ -922,9 +923,9 @@ void main_1() {
|
||||||
i_2 = 0;
|
i_2 = 0;
|
||||||
i_2 = x_774;
|
i_2 = x_774;
|
||||||
const QuicksortObject x_775 = obj;
|
const QuicksortObject x_775 = obj;
|
||||||
const tint_array_wrapper tint_symbol_58 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_59 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_59 = {tint_symbol_58};
|
const QuicksortObject tint_symbol_60 = {tint_symbol_59};
|
||||||
obj = tint_symbol_59;
|
obj = tint_symbol_60;
|
||||||
obj = x_775;
|
obj = x_775;
|
||||||
const float3 x_453 = float3(x_451.x, x_450.x, x_450.y);
|
const float3 x_453 = float3(x_451.x, x_450.x, x_450.y);
|
||||||
color.x = (x_206 + float(x_201));
|
color.x = (x_206 + float(x_201));
|
||||||
|
@ -941,9 +942,9 @@ void main_1() {
|
||||||
uv.x = 0.0f;
|
uv.x = 0.0f;
|
||||||
uv.x = x_778;
|
uv.x = x_778;
|
||||||
const QuicksortObject x_779 = obj;
|
const QuicksortObject x_779 = obj;
|
||||||
const tint_array_wrapper tint_symbol_60 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_61 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_61 = {tint_symbol_60};
|
const QuicksortObject tint_symbol_62 = {tint_symbol_61};
|
||||||
obj = tint_symbol_61;
|
obj = tint_symbol_62;
|
||||||
obj = x_779;
|
obj = x_779;
|
||||||
if ((x_210 > 0.25f)) {
|
if ((x_210 > 0.25f)) {
|
||||||
const int x_780 = i_2;
|
const int x_780 = i_2;
|
||||||
|
@ -958,18 +959,18 @@ void main_1() {
|
||||||
uv.x = x_782;
|
uv.x = x_782;
|
||||||
const int x_216 = obj.numbers.arr[1];
|
const int x_216 = obj.numbers.arr[1];
|
||||||
const QuicksortObject x_783 = obj;
|
const QuicksortObject x_783 = obj;
|
||||||
const tint_array_wrapper tint_symbol_62 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_63 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_63 = {tint_symbol_62};
|
const QuicksortObject tint_symbol_64 = {tint_symbol_63};
|
||||||
obj = tint_symbol_63;
|
obj = tint_symbol_64;
|
||||||
obj = x_783;
|
obj = x_783;
|
||||||
const float2 x_457 = float2(x_454.x, x_454.x);
|
const float2 x_457 = float2(x_454.x, x_454.x);
|
||||||
const float2 x_784 = uv;
|
const float2 x_784 = uv;
|
||||||
uv = float2(0.0f, 0.0f);
|
uv = float2(0.0f, 0.0f);
|
||||||
uv = x_784;
|
uv = x_784;
|
||||||
const QuicksortObject x_785 = obj;
|
const QuicksortObject x_785 = obj;
|
||||||
const tint_array_wrapper tint_symbol_64 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_65 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_65 = {tint_symbol_64};
|
const QuicksortObject tint_symbol_66 = {tint_symbol_65};
|
||||||
obj = tint_symbol_65;
|
obj = tint_symbol_66;
|
||||||
obj = x_785;
|
obj = x_785;
|
||||||
const float2 x_458 = float2(float3(1.0f, 2.0f, 3.0f).z, float2(0.0f, 0.0f).y);
|
const float2 x_458 = float2(float3(1.0f, 2.0f, 3.0f).z, float2(0.0f, 0.0f).y);
|
||||||
const int x_786 = i_2;
|
const int x_786 = i_2;
|
||||||
|
@ -1087,9 +1088,9 @@ void main_1() {
|
||||||
color.x = 0.0f;
|
color.x = 0.0f;
|
||||||
color.x = x_816;
|
color.x = x_816;
|
||||||
const QuicksortObject x_817 = obj;
|
const QuicksortObject x_817 = obj;
|
||||||
const tint_array_wrapper tint_symbol_66 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_67 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_67 = {tint_symbol_66};
|
const QuicksortObject tint_symbol_68 = {tint_symbol_67};
|
||||||
obj = tint_symbol_67;
|
obj = tint_symbol_68;
|
||||||
obj = x_817;
|
obj = x_817;
|
||||||
const float3 x_468 = float3(x_467.x, x_467.x, x_467.x);
|
const float3 x_468 = float3(x_467.x, x_467.x, x_467.x);
|
||||||
const float x_818 = uv[0];
|
const float x_818 = uv[0];
|
||||||
|
@ -1198,9 +1199,9 @@ void main_1() {
|
||||||
uv[0] = x_844;
|
uv[0] = x_844;
|
||||||
const float3 x_482 = float3(x_455.x, x_475.y, x_455.y);
|
const float3 x_482 = float3(x_455.x, x_475.y, x_455.y);
|
||||||
const QuicksortObject x_845 = obj;
|
const QuicksortObject x_845 = obj;
|
||||||
const tint_array_wrapper tint_symbol_68 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_69 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_69 = {tint_symbol_68};
|
const QuicksortObject tint_symbol_70 = {tint_symbol_69};
|
||||||
obj = tint_symbol_69;
|
obj = tint_symbol_70;
|
||||||
obj = x_845;
|
obj = x_845;
|
||||||
const float x_846 = uv.y;
|
const float x_846 = uv.y;
|
||||||
uv.y = 0.0f;
|
uv.y = 0.0f;
|
||||||
|
@ -1271,9 +1272,9 @@ void main_1() {
|
||||||
obj.numbers.arr[6u] = x_863;
|
obj.numbers.arr[6u] = x_863;
|
||||||
const float2 x_490 = float2(x_480.z, x_480.z);
|
const float2 x_490 = float2(x_480.z, x_480.z);
|
||||||
const QuicksortObject x_864 = obj;
|
const QuicksortObject x_864 = obj;
|
||||||
const tint_array_wrapper tint_symbol_70 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_71 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_71 = {tint_symbol_70};
|
const QuicksortObject tint_symbol_72 = {tint_symbol_71};
|
||||||
obj = tint_symbol_71;
|
obj = tint_symbol_72;
|
||||||
obj = x_864;
|
obj = x_864;
|
||||||
color.y = (float(x_280) + x_283);
|
color.y = (float(x_280) + x_283);
|
||||||
const float x_865 = color.x;
|
const float x_865 = color.x;
|
||||||
|
@ -1290,9 +1291,9 @@ void main_1() {
|
||||||
color.x = x_867;
|
color.x = x_867;
|
||||||
const float x_287 = uv.y;
|
const float x_287 = uv.y;
|
||||||
const QuicksortObject x_868 = obj;
|
const QuicksortObject x_868 = obj;
|
||||||
const tint_array_wrapper tint_symbol_72 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_73 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_73 = {tint_symbol_72};
|
const QuicksortObject tint_symbol_74 = {tint_symbol_73};
|
||||||
obj = tint_symbol_73;
|
obj = tint_symbol_74;
|
||||||
obj = x_868;
|
obj = x_868;
|
||||||
const float2 x_493 = float2(x_475.x, x_475.y);
|
const float2 x_493 = float2(x_475.x, x_475.y);
|
||||||
const float x_869 = uv[0];
|
const float x_869 = uv[0];
|
||||||
|
@ -1452,9 +1453,9 @@ void main_1() {
|
||||||
uv.x = 0.0f;
|
uv.x = 0.0f;
|
||||||
uv.x = x_910;
|
uv.x = x_910;
|
||||||
const QuicksortObject x_911 = obj;
|
const QuicksortObject x_911 = obj;
|
||||||
const tint_array_wrapper tint_symbol_74 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_75 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_75 = {tint_symbol_74};
|
const QuicksortObject tint_symbol_76 = {tint_symbol_75};
|
||||||
obj = tint_symbol_75;
|
obj = tint_symbol_76;
|
||||||
obj = x_911;
|
obj = x_911;
|
||||||
const float3 x_513 = float3(x_505.z, x_505.x, x_448.x);
|
const float3 x_513 = float3(x_505.z, x_505.x, x_448.x);
|
||||||
const int x_912 = obj.numbers.arr[8];
|
const int x_912 = obj.numbers.arr[8];
|
||||||
|
@ -1506,14 +1507,14 @@ void main_1() {
|
||||||
uv.x = 0.0f;
|
uv.x = 0.0f;
|
||||||
uv.x = x_923;
|
uv.x = x_923;
|
||||||
const QuicksortObject x_924 = obj;
|
const QuicksortObject x_924 = obj;
|
||||||
const tint_array_wrapper tint_symbol_76 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_77 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_77 = {tint_symbol_76};
|
const QuicksortObject tint_symbol_78 = {tint_symbol_77};
|
||||||
obj = tint_symbol_77;
|
obj = tint_symbol_78;
|
||||||
obj = x_924;
|
obj = x_924;
|
||||||
const QuicksortObject x_925 = obj;
|
const QuicksortObject x_925 = obj;
|
||||||
const tint_array_wrapper tint_symbol_78 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_79 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_79 = {tint_symbol_78};
|
const QuicksortObject tint_symbol_80 = {tint_symbol_79};
|
||||||
obj = tint_symbol_79;
|
obj = tint_symbol_80;
|
||||||
obj = x_925;
|
obj = x_925;
|
||||||
const float x_926 = color.y;
|
const float x_926 = color.y;
|
||||||
color.y = 0.0f;
|
color.y = 0.0f;
|
||||||
|
@ -1532,9 +1533,9 @@ void main_1() {
|
||||||
uv.x = x_929;
|
uv.x = x_929;
|
||||||
x_GLF_color = x_330;
|
x_GLF_color = x_330;
|
||||||
const QuicksortObject x_930 = obj;
|
const QuicksortObject x_930 = obj;
|
||||||
const tint_array_wrapper tint_symbol_80 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
const tint_array_wrapper tint_symbol_81 = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
const QuicksortObject tint_symbol_81 = {tint_symbol_80};
|
const QuicksortObject tint_symbol_82 = {tint_symbol_81};
|
||||||
obj = tint_symbol_81;
|
obj = tint_symbol_82;
|
||||||
obj = x_930;
|
obj = x_930;
|
||||||
const float3 x_522 = float3(x_330.w, x_330.y, x_493.x);
|
const float3 x_522 = float3(x_330.w, x_330.y, x_493.x);
|
||||||
const float x_931 = color.x;
|
const float x_931 = color.x;
|
||||||
|
@ -1558,6 +1559,6 @@ tint_symbol_2 main(tint_symbol_1 tint_symbol) {
|
||||||
gl_FragCoord = gl_FragCoord_param;
|
gl_FragCoord = gl_FragCoord_param;
|
||||||
main_1();
|
main_1();
|
||||||
const main_out tint_symbol_3 = {x_GLF_color};
|
const main_out tint_symbol_3 = {x_GLF_color};
|
||||||
const tint_symbol_2 tint_symbol_82 = {tint_symbol_3.x_GLF_color};
|
const tint_symbol_2 tint_symbol_83 = {tint_symbol_3.x_GLF_color};
|
||||||
return tint_symbol_82;
|
return tint_symbol_83;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
struct Constants {
|
cbuffer cbuffer_constants : register(b0, space0) {
|
||||||
/* 0x0000 */ int level;
|
uint4 constants[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
ConstantBuffer<Constants> constants : register(b0, space0);
|
|
||||||
Texture2DArray<float4> myTexture : register(t1, space0);
|
Texture2DArray<float4> myTexture : register(t1, space0);
|
||||||
|
|
||||||
RWByteAddressBuffer result : register(u3, space0);
|
RWByteAddressBuffer result : register(u3, space0);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
struct tint_array_wrapper {
|
struct tint_array_wrapper {
|
||||||
/* 0x0000 */ int arr[6];
|
int arr[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_array_wrapper tint_symbol_1(ByteAddressBuffer buffer, uint offset) {
|
tint_array_wrapper tint_symbol_1(ByteAddressBuffer buffer, uint offset) {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
struct S {
|
cbuffer cbuffer_v : register(b0, space0) {
|
||||||
/* 0x0000 */ int a;
|
uint4 v[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
ConstantBuffer<S> v : register(b0, space0);
|
|
||||||
|
|
||||||
[numthreads(1, 1, 1)]
|
[numthreads(1, 1, 1)]
|
||||||
void main() {
|
void main() {
|
||||||
const int use = (v.a + 1);
|
const int scalar_offset = (0u) / 4;
|
||||||
|
const int use = (asint(v[scalar_offset / 4][scalar_offset % 4]) + 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ tint_symbol_2 vert_main(tint_symbol_1 tint_symbol) {
|
||||||
const float2 a_pos = tint_symbol.a_pos;
|
const float2 a_pos = tint_symbol.a_pos;
|
||||||
float angle = -(atan2(a_particleVel.x, a_particleVel.y));
|
float angle = -(atan2(a_particleVel.x, a_particleVel.y));
|
||||||
float2 pos = float2(((a_pos.x * cos(angle)) - (a_pos.y * sin(angle))), ((a_pos.x * sin(angle)) + (a_pos.y * cos(angle))));
|
float2 pos = float2(((a_pos.x * cos(angle)) - (a_pos.y * sin(angle))), ((a_pos.x * sin(angle)) + (a_pos.y * cos(angle))));
|
||||||
const tint_symbol_2 tint_symbol_8 = {float4((pos + a_particlePos), 0.0f, 1.0f)};
|
const tint_symbol_2 tint_symbol_9 = {float4((pos + a_particlePos), 0.0f, 1.0f)};
|
||||||
return tint_symbol_8;
|
return tint_symbol_9;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tint_symbol_3 {
|
struct tint_symbol_3 {
|
||||||
|
@ -22,21 +22,13 @@ struct tint_symbol_3 {
|
||||||
};
|
};
|
||||||
|
|
||||||
tint_symbol_3 frag_main() {
|
tint_symbol_3 frag_main() {
|
||||||
const tint_symbol_3 tint_symbol_9 = {float4(1.0f, 1.0f, 1.0f, 1.0f)};
|
const tint_symbol_3 tint_symbol_10 = {float4(1.0f, 1.0f, 1.0f, 1.0f)};
|
||||||
return tint_symbol_9;
|
return tint_symbol_10;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimParams {
|
cbuffer cbuffer_params : register(b0, space0) {
|
||||||
/* 0x0000 */ float deltaT;
|
uint4 params[2];
|
||||||
/* 0x0004 */ float rule1Distance;
|
|
||||||
/* 0x0008 */ float rule2Distance;
|
|
||||||
/* 0x000c */ float rule3Distance;
|
|
||||||
/* 0x0010 */ float rule1Scale;
|
|
||||||
/* 0x0014 */ float rule2Scale;
|
|
||||||
/* 0x0018 */ float rule3Scale;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ConstantBuffer<SimParams> params : register(b0, space0);
|
|
||||||
RWByteAddressBuffer particlesA : register(u1, space0);
|
RWByteAddressBuffer particlesA : register(u1, space0);
|
||||||
RWByteAddressBuffer particlesB : register(u2, space0);
|
RWByteAddressBuffer particlesB : register(u2, space0);
|
||||||
|
|
||||||
|
@ -74,14 +66,17 @@ void comp_main(tint_symbol_5 tint_symbol_4) {
|
||||||
}
|
}
|
||||||
pos = asfloat(particlesA.Load2((16u * i))).xy;
|
pos = asfloat(particlesA.Load2((16u * i))).xy;
|
||||||
vel = asfloat(particlesA.Load2(((16u * i) + 8u))).xy;
|
vel = asfloat(particlesA.Load2(((16u * i) + 8u))).xy;
|
||||||
if ((distance(pos, vPos) < params.rule1Distance)) {
|
const int scalar_offset = (4u) / 4;
|
||||||
|
if ((distance(pos, vPos) < asfloat(params[scalar_offset / 4][scalar_offset % 4]))) {
|
||||||
cMass = (cMass + pos);
|
cMass = (cMass + pos);
|
||||||
cMassCount = (cMassCount + 1);
|
cMassCount = (cMassCount + 1);
|
||||||
}
|
}
|
||||||
if ((distance(pos, vPos) < params.rule2Distance)) {
|
const int scalar_offset_1 = (8u) / 4;
|
||||||
|
if ((distance(pos, vPos) < asfloat(params[scalar_offset_1 / 4][scalar_offset_1 % 4]))) {
|
||||||
colVel = (colVel - (pos - vPos));
|
colVel = (colVel - (pos - vPos));
|
||||||
}
|
}
|
||||||
if ((distance(pos, vPos) < params.rule3Distance)) {
|
const int scalar_offset_2 = (12u) / 4;
|
||||||
|
if ((distance(pos, vPos) < asfloat(params[scalar_offset_2 / 4][scalar_offset_2 % 4]))) {
|
||||||
cVel = (cVel + vel);
|
cVel = (cVel + vel);
|
||||||
cVelCount = (cVelCount + 1);
|
cVelCount = (cVelCount + 1);
|
||||||
}
|
}
|
||||||
|
@ -96,9 +91,13 @@ void comp_main(tint_symbol_5 tint_symbol_4) {
|
||||||
if ((cVelCount > 0)) {
|
if ((cVelCount > 0)) {
|
||||||
cVel = (cVel / float2(float(cVelCount), float(cVelCount)));
|
cVel = (cVel / float2(float(cVelCount), float(cVelCount)));
|
||||||
}
|
}
|
||||||
vVel = (((vVel + (cMass * params.rule1Scale)) + (colVel * params.rule2Scale)) + (cVel * params.rule3Scale));
|
const int scalar_offset_3 = (16u) / 4;
|
||||||
|
const int scalar_offset_4 = (20u) / 4;
|
||||||
|
const int scalar_offset_5 = (24u) / 4;
|
||||||
|
vVel = (((vVel + (cMass * asfloat(params[scalar_offset_3 / 4][scalar_offset_3 % 4]))) + (colVel * asfloat(params[scalar_offset_4 / 4][scalar_offset_4 % 4]))) + (cVel * asfloat(params[scalar_offset_5 / 4][scalar_offset_5 % 4])));
|
||||||
vVel = (normalize(vVel) * clamp(length(vVel), 0.0f, 0.100000001f));
|
vVel = (normalize(vVel) * clamp(length(vVel), 0.0f, 0.100000001f));
|
||||||
vPos = (vPos + (vVel * params.deltaT));
|
const int scalar_offset_6 = (0u) / 4;
|
||||||
|
vPos = (vPos + (vVel * asfloat(params[scalar_offset_6 / 4][scalar_offset_6 % 4])));
|
||||||
if ((vPos.x < -1.0f)) {
|
if ((vPos.x < -1.0f)) {
|
||||||
vPos.x = 1.0f;
|
vPos.x = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
struct Uniforms {
|
float4x4 tint_symbol_7(uint4 buffer[4], uint offset) {
|
||||||
/* 0x0000 */ float4x4 modelViewProjectionMatrix;
|
const int scalar_offset = ((offset + 0u)) / 4;
|
||||||
};
|
const int scalar_offset_1 = ((offset + 16u)) / 4;
|
||||||
|
const int scalar_offset_2 = ((offset + 32u)) / 4;
|
||||||
|
const int scalar_offset_3 = ((offset + 48u)) / 4;
|
||||||
|
return float4x4(asfloat(buffer[scalar_offset / 4]), asfloat(buffer[scalar_offset_1 / 4]), asfloat(buffer[scalar_offset_2 / 4]), asfloat(buffer[scalar_offset_3 / 4]));
|
||||||
|
}
|
||||||
|
|
||||||
ConstantBuffer<Uniforms> uniforms : register(b0, space0);
|
cbuffer cbuffer_uniforms : register(b0, space0) {
|
||||||
|
uint4 uniforms[4];
|
||||||
|
};
|
||||||
|
|
||||||
struct VertexInput {
|
struct VertexInput {
|
||||||
float4 cur_position;
|
float4 cur_position;
|
||||||
|
@ -24,10 +30,10 @@ struct tint_symbol_2 {
|
||||||
tint_symbol_2 vtx_main(tint_symbol_1 tint_symbol) {
|
tint_symbol_2 vtx_main(tint_symbol_1 tint_symbol) {
|
||||||
const VertexInput input = {tint_symbol.cur_position, tint_symbol.color};
|
const VertexInput input = {tint_symbol.cur_position, tint_symbol.color};
|
||||||
VertexOutput output = {float4(0.0f, 0.0f, 0.0f, 0.0f), float4(0.0f, 0.0f, 0.0f, 0.0f)};
|
VertexOutput output = {float4(0.0f, 0.0f, 0.0f, 0.0f), float4(0.0f, 0.0f, 0.0f, 0.0f)};
|
||||||
output.Position = mul(input.cur_position, uniforms.modelViewProjectionMatrix);
|
output.Position = mul(input.cur_position, tint_symbol_7(uniforms, 0u));
|
||||||
output.vtxFragColor = input.color;
|
output.vtxFragColor = input.color;
|
||||||
const tint_symbol_2 tint_symbol_6 = {output.vtxFragColor, output.Position};
|
const tint_symbol_2 tint_symbol_8 = {output.vtxFragColor, output.Position};
|
||||||
return tint_symbol_6;
|
return tint_symbol_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tint_symbol_4 {
|
struct tint_symbol_4 {
|
||||||
|
@ -39,6 +45,6 @@ struct tint_symbol_5 {
|
||||||
|
|
||||||
tint_symbol_5 frag_main(tint_symbol_4 tint_symbol_3) {
|
tint_symbol_5 frag_main(tint_symbol_4 tint_symbol_3) {
|
||||||
const float4 fragColor = tint_symbol_3.fragColor;
|
const float4 fragColor = tint_symbol_3.fragColor;
|
||||||
const tint_symbol_5 tint_symbol_7 = {fragColor};
|
const tint_symbol_5 tint_symbol_9 = {fragColor};
|
||||||
return tint_symbol_7;
|
return tint_symbol_9;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,9 @@
|
||||||
struct S {
|
struct S {
|
||||||
/* 0x0000 */ float f;
|
float f;
|
||||||
/* 0x0004 */ uint u;
|
uint u;
|
||||||
/* 0x0008 */ int tint_pad_0[30];
|
float4 v;
|
||||||
/* 0x0080 */ float4 v;
|
|
||||||
/* 0x0090 */ int tint_pad_1[28];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
S make_S(float param_0,
|
|
||||||
uint param_1,
|
|
||||||
float4 param_2) {
|
|
||||||
S output;
|
|
||||||
output.f = param_0;
|
|
||||||
output.u = param_1;
|
|
||||||
output.v = param_2;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tint_symbol_5(RWByteAddressBuffer buffer, uint offset, S value) {
|
void tint_symbol_5(RWByteAddressBuffer buffer, uint offset, S value) {
|
||||||
buffer.Store((offset + 0u), asuint(value.f));
|
buffer.Store((offset + 0u), asuint(value.f));
|
||||||
buffer.Store((offset + 4u), asuint(value.u));
|
buffer.Store((offset + 4u), asuint(value.u));
|
||||||
|
@ -31,7 +19,7 @@ struct tint_symbol_1 {
|
||||||
};
|
};
|
||||||
|
|
||||||
void frag_main(tint_symbol_1 tint_symbol) {
|
void frag_main(tint_symbol_1 tint_symbol) {
|
||||||
const S input = make_S(tint_symbol.f, tint_symbol.u, tint_symbol.v);
|
const S input = {tint_symbol.f, tint_symbol.u, tint_symbol.v};
|
||||||
const float f = input.f;
|
const float f = input.f;
|
||||||
const uint u = input.u;
|
const uint u = input.u;
|
||||||
const float4 v = input.v;
|
const float4 v = input.v;
|
||||||
|
|
Loading…
Reference in New Issue