Add option to auto generate bindings for external textures

With this change, the backend sanitizers always run the
MultiplanarExternalTexture transform. If the new option is enabled, it
auto-generates bindings for this transform.

This change also enables this auto-generation for the Tint commandline
application, as well as for the fuzzers.

Bug: chromium:1310623
Change-Id: I3c661c4753dc67c0212051d09024cbeda3939f8c
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/85542
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
Antonio Maiorano
2022-04-06 13:57:54 +00:00
committed by Tint LUCI CQ
parent 12f2f9b1bc
commit a730eb738e
44 changed files with 2006 additions and 113 deletions

View File

@@ -527,6 +527,8 @@ libtint_source_set("libtint_core_all_src") {
"writer/array_length_from_uniform_options.h",
"writer/float_to_string.cc",
"writer/float_to_string.h",
"writer/generate_external_texture_bindings.cc",
"writer/generate_external_texture_bindings.h",
"writer/text.cc",
"writer/text.h",
"writer/text_generator.cc",

View File

@@ -451,6 +451,8 @@ set(TINT_LIB_SRCS
writer/array_length_from_uniform_options.h
writer/float_to_string.cc
writer/float_to_string.h
writer/generate_external_texture_bindings.cc
writer/generate_external_texture_bindings.h
writer/text_generator.cc
writer/text_generator.h
writer/text.cc
@@ -810,6 +812,7 @@ if(TINT_BUILD_TESTS)
utils/unique_vector_test.cc
writer/append_vector_test.cc
writer/float_to_string_test.cc
writer/generate_external_texture_bindings_test.cc
writer/text_generator_test.cc
)

View File

@@ -569,6 +569,7 @@ bool GenerateSpirv(const tint::Program* program, const Options& options) {
// TODO(jrprice): Provide a way for the user to set non-default options.
tint::writer::spirv::Options gen_options;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
gen_options.generate_external_texture_bindings = true;
auto result = tint::writer::spirv::Generate(program, gen_options);
if (!result.success) {
PrintWGSL(std::cerr, *program);
@@ -717,6 +718,7 @@ bool GenerateMsl(const tint::Program* program, const Options& options) {
// TODO(jrprice): Provide a way for the user to set non-default options.
tint::writer::msl::Options gen_options;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
gen_options.generate_external_texture_bindings = true;
auto result = tint::writer::msl::Generate(input_program, gen_options);
if (!result.success) {
PrintWGSL(std::cerr, *program);
@@ -771,6 +773,7 @@ bool GenerateHlsl(const tint::Program* program, const Options& options) {
// TODO(jrprice): Provide a way for the user to set non-default options.
tint::writer::hlsl::Options gen_options;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
gen_options.generate_external_texture_bindings = true;
auto result = tint::writer::hlsl::Generate(program, gen_options);
if (!result.success) {
PrintWGSL(std::cerr, *program);
@@ -846,6 +849,7 @@ bool GenerateGlsl(const tint::Program* program, const Options& options) {
auto generate = [&](const tint::Program* prg,
const std::string entry_point_name) -> bool {
tint::writer::glsl::Options gen_options;
gen_options.generate_external_texture_bindings = true;
auto result =
tint::writer::glsl::Generate(prg, gen_options, entry_point_name);
if (!result.success) {

View File

@@ -172,6 +172,7 @@ class DataBuilder {
b->build(out.fixed_sample_mask);
b->build(out.emit_vertex_point_size);
b->build(out.disable_workgroup_init);
b->build(out.generate_external_texture_bindings);
b->build(out.array_length_from_uniform);
return out;
}

View File

@@ -37,6 +37,7 @@
#include "src/tint/transform/unshadow.h"
#include "src/tint/transform/unwind_discard_functions.h"
#include "src/tint/transform/zero_init_workgroup_memory.h"
#include "src/tint/writer/generate_external_texture_bindings.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::Glsl);
TINT_INSTANTIATE_TYPEINFO(tint::transform::Glsl::Config);
@@ -91,6 +92,13 @@ Output Glsl::Run(const Program* in, const DataMap& inputs) const {
manager.Add<SimplifyPointers>();
manager.Add<RemovePhonies>();
if (cfg && cfg->generate_external_texture_bindings) {
auto new_bindings_map = writer::GenerateExternalTextureBindings(in);
data.Add<MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
}
manager.Add<MultiplanarExternalTexture>();
manager.Add<CombineSamplers>();
if (auto* binding_info = inputs.Get<CombineSamplers::BindingInfo>()) {
data.Add<CombineSamplers::BindingInfo>(*binding_info);
@@ -106,6 +114,7 @@ Output Glsl::Run(const Program* in, const DataMap& inputs) const {
BindingRemapper::AccessControls ac;
data.Add<BindingRemapper::Remappings>(bp, ac, /* mayCollide */ true);
}
manager.Add<PromoteInitializersToConstVar>();
manager.Add<AddEmptyEntryPoint>();
@@ -124,8 +133,13 @@ Output Glsl::Run(const Program* in, const DataMap& inputs) const {
return Output{Program(std::move(builder))};
}
Glsl::Config::Config(const std::string& ep, bool disable_wi)
: entry_point(ep), disable_workgroup_init(disable_wi) {}
Glsl::Config::Config(const std::string& entry_point_in,
bool disable_workgroup_init_in,
bool generate_external_texture_bindings_in)
: entry_point(entry_point_in),
disable_workgroup_init(disable_workgroup_init_in),
generate_external_texture_bindings(
generate_external_texture_bindings_in) {}
Glsl::Config::Config(const Config&) = default;
Glsl::Config::~Config() = default;

View File

@@ -37,8 +37,11 @@ class Glsl final : public Castable<Glsl, Transform> {
/// @param entry_point the root entry point function to generate
/// @param disable_workgroup_init `true` to disable workgroup memory zero
/// initialization
/// @param generate_external_texture_bindings 'true' to generates binding
/// mappings for external textures
explicit Config(const std::string& entry_point,
bool disable_workgroup_init = false);
bool disable_workgroup_init,
bool generate_external_texture_bindings);
/// Copy constructor
Config(const Config&);
@@ -51,6 +54,9 @@ class Glsl final : public Castable<Glsl, Transform> {
/// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false;
/// Set to 'true' to generates binding mappings for external textures
bool generate_external_texture_bindings = false;
};
/// Constructor

View File

@@ -0,0 +1,59 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/tint/writer/generate_external_texture_bindings.h"
#include <algorithm>
#include <unordered_map>
#include <vector>
#include "src/tint/ast/external_texture.h"
#include "src/tint/ast/module.h"
#include "src/tint/program.h"
#include "src/tint/sem/external_texture_type.h"
#include "src/tint/sem/variable.h"
namespace tint::writer {
transform::MultiplanarExternalTexture::BindingsMap
GenerateExternalTextureBindings(const Program* program) {
// TODO(tint:1491): Use Inspector once we can get binding info for all
// variables, not just those referenced by entry points.
// Collect next valid binding number per group
std::unordered_map<uint32_t, uint32_t> group_to_next_binding_number;
std::vector<sem::BindingPoint> ext_tex_bps;
for (auto* var : program->AST().GlobalVariables()) {
if (auto* sem_var = program->Sem().Get(var)->As<sem::GlobalVariable>()) {
auto bp = sem_var->BindingPoint();
auto& n = group_to_next_binding_number[bp.group];
n = std::max(n, bp.binding + 1);
if (sem_var->Type()->UnwrapRef()->Is<sem::ExternalTexture>()) {
ext_tex_bps.emplace_back(bp);
}
}
}
transform::MultiplanarExternalTexture::BindingsMap new_bindings_map;
for (auto bp : ext_tex_bps) {
uint32_t g = bp.group;
uint32_t& next_num = group_to_next_binding_number[g];
auto new_bps = transform::BindingPoints{{g, next_num++}, {g, next_num++}};
new_bindings_map[bp] = new_bps;
}
return new_bindings_map;
}
} // namespace tint::writer

View File

@@ -0,0 +1,27 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_TINT_WRITER_GENERATE_EXTERNAL_TEXTURE_BINDINGS_H_
#define SRC_TINT_WRITER_GENERATE_EXTERNAL_TEXTURE_BINDINGS_H_
#include "src/tint/transform/multiplanar_external_texture.h"
namespace tint::writer {
transform::MultiplanarExternalTexture::BindingsMap
GenerateExternalTextureBindings(const Program* program);
} // namespace tint::writer
#endif // SRC_TINT_WRITER_GENERATE_EXTERNAL_TEXTURE_BINDINGS_H_

View File

@@ -0,0 +1,131 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <utility>
#include "gtest/gtest.h"
#include "src/tint/program_builder.h"
#include "src/tint/writer/generate_external_texture_bindings.h"
namespace tint::writer {
namespace {
constexpr auto kUniform = ast::StorageClass::kUniform;
class GenerateExternalTextureBindingsTest : public ::testing::Test {};
TEST_F(GenerateExternalTextureBindingsTest, None) {
ProgramBuilder b;
b.WrapInFunction();
tint::Program program(std::move(b));
ASSERT_TRUE(program.IsValid());
auto bindings = GenerateExternalTextureBindings(&program);
ASSERT_TRUE(bindings.empty());
}
TEST_F(GenerateExternalTextureBindingsTest, One) {
ProgramBuilder b;
b.Global("v0", b.ty.external_texture(), b.GroupAndBinding(0, 0));
b.WrapInFunction();
tint::Program program(std::move(b));
ASSERT_TRUE(program.IsValid());
auto bindings = GenerateExternalTextureBindings(&program);
ASSERT_EQ(bindings.size(), 1u);
auto to = bindings[transform::BindingPoint{0, 0}];
ASSERT_EQ(to.plane_1.group, 0u);
ASSERT_EQ(to.params.group, 0u);
ASSERT_EQ(to.plane_1.binding, 1u);
ASSERT_EQ(to.params.binding, 2u);
}
TEST_F(GenerateExternalTextureBindingsTest, Two_SameGroup) {
ProgramBuilder b;
b.Global("v0", b.ty.external_texture(), b.GroupAndBinding(0, 0));
b.Global("v1", b.ty.external_texture(), b.GroupAndBinding(0, 1));
b.WrapInFunction();
tint::Program program(std::move(b));
ASSERT_TRUE(program.IsValid());
auto bindings = GenerateExternalTextureBindings(&program);
ASSERT_EQ(bindings.size(), 2u);
auto to0 = bindings[transform::BindingPoint{0, 0}];
ASSERT_EQ(to0.plane_1.group, 0u);
ASSERT_EQ(to0.params.group, 0u);
ASSERT_EQ(to0.plane_1.binding, 2u);
ASSERT_EQ(to0.params.binding, 3u);
auto to1 = bindings[transform::BindingPoint{0, 1}];
ASSERT_EQ(to1.plane_1.group, 0u);
ASSERT_EQ(to1.params.group, 0u);
ASSERT_EQ(to1.plane_1.binding, 4u);
ASSERT_EQ(to1.params.binding, 5u);
}
TEST_F(GenerateExternalTextureBindingsTest, Two_DifferentGroup) {
ProgramBuilder b;
b.Global("v0", b.ty.external_texture(), b.GroupAndBinding(0, 0));
b.Global("v1", b.ty.external_texture(), b.GroupAndBinding(1, 0));
b.WrapInFunction();
tint::Program program(std::move(b));
ASSERT_TRUE(program.IsValid());
auto bindings = GenerateExternalTextureBindings(&program);
ASSERT_EQ(bindings.size(), 2u);
auto to0 = bindings[transform::BindingPoint{0, 0}];
ASSERT_EQ(to0.plane_1.group, 0u);
ASSERT_EQ(to0.params.group, 0u);
ASSERT_EQ(to0.plane_1.binding, 1u);
ASSERT_EQ(to0.params.binding, 2u);
auto to1 = bindings[transform::BindingPoint{1, 0}];
ASSERT_EQ(to1.plane_1.group, 1u);
ASSERT_EQ(to1.params.group, 1u);
ASSERT_EQ(to1.plane_1.binding, 1u);
ASSERT_EQ(to1.params.binding, 2u);
}
TEST_F(GenerateExternalTextureBindingsTest, Two_WithOtherBindingsInSameGroup) {
ProgramBuilder b;
b.Global("v0", b.ty.i32(), b.GroupAndBinding(0, 0), kUniform);
b.Global("v1", b.ty.external_texture(), b.GroupAndBinding(0, 1));
b.Global("v2", b.ty.i32(), b.GroupAndBinding(0, 2), kUniform);
b.Global("v3", b.ty.external_texture(), b.GroupAndBinding(0, 3));
b.Global("v4", b.ty.i32(), b.GroupAndBinding(0, 4), kUniform);
b.WrapInFunction();
tint::Program program(std::move(b));
ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str();
auto bindings = GenerateExternalTextureBindings(&program);
ASSERT_EQ(bindings.size(), 2u);
auto to0 = bindings[transform::BindingPoint{0, 1}];
ASSERT_EQ(to0.plane_1.group, 0u);
ASSERT_EQ(to0.params.group, 0u);
ASSERT_EQ(to0.plane_1.binding, 5u);
ASSERT_EQ(to0.params.binding, 6u);
auto to1 = bindings[transform::BindingPoint{0, 3}];
ASSERT_EQ(to1.plane_1.group, 0u);
ASSERT_EQ(to1.params.group, 0u);
ASSERT_EQ(to1.plane_1.binding, 7u);
ASSERT_EQ(to1.params.binding, 8u);
}
} // namespace
} // namespace tint::writer

View File

@@ -43,7 +43,9 @@ Result Generate(const Program* program,
options.allow_collisions);
data.Add<transform::CombineSamplers::BindingInfo>(
options.binding_map, options.placeholder_binding_point);
data.Add<transform::Glsl::Config>(entry_point);
data.Add<transform::Glsl::Config>(entry_point,
/* disable_workgroup_init */ false,
options.generate_external_texture_bindings);
transform::Glsl sanitizer;
auto output = sanitizer.Run(program, data);
if (!output.program.IsValid()) {

View File

@@ -71,6 +71,9 @@ struct Options {
/// generated by the BindingRemapper transform
bool allow_collisions = false;
/// Set to 'true' to generates binding mappings for external textures
bool generate_external_texture_bindings = false;
/// The GLSL version to emit
Version version;
};

View File

@@ -35,6 +35,7 @@ Result Generate(const Program* program, const Options& options) {
// Sanitize the program.
auto sanitized_result = Sanitize(program, options.root_constant_binding_point,
options.disable_workgroup_init,
options.generate_external_texture_bindings,
options.array_length_from_uniform);
if (!sanitized_result.program.IsValid()) {
result.success = false;

View File

@@ -53,6 +53,8 @@ struct Options {
sem::BindingPoint root_constant_binding_point;
/// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false;
/// Set to 'true' to generates binding mappings for external textures
bool generate_external_texture_bindings = false;
/// Options used to specify a mapping of binding points to indices into a UBO
/// from which to load buffer sizes.
ArrayLengthFromUniformOptions array_length_from_uniform = {};

View File

@@ -71,6 +71,7 @@
#include "src/tint/utils/scoped_assignment.h"
#include "src/tint/writer/append_vector.h"
#include "src/tint/writer/float_to_string.h"
#include "src/tint/writer/generate_external_texture_bindings.h"
namespace tint {
namespace writer {
@@ -139,6 +140,7 @@ SanitizedResult Sanitize(
const Program* in,
sem::BindingPoint root_constant_binding_point,
bool disable_workgroup_init,
bool generate_external_texture_bindings,
const ArrayLengthFromUniformOptions& array_length_from_uniform) {
transform::Manager manager;
transform::DataMap data;
@@ -163,6 +165,13 @@ SanitizedResult Sanitize(
array_length_from_uniform_cfg.bindpoint_to_size_index =
array_length_from_uniform.bindpoint_to_size_index;
if (generate_external_texture_bindings) {
auto new_bindings_map = GenerateExternalTextureBindings(in);
data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
new_bindings_map);
}
manager.Add<transform::MultiplanarExternalTexture>();
manager.Add<transform::Unshadow>();
// LocalizeStructArrayAssignment must come after:

View File

@@ -77,6 +77,7 @@ SanitizedResult Sanitize(
const Program* program,
sem::BindingPoint root_constant_binding_point = {},
bool disable_workgroup_init = false,
bool generate_external_texture_bindings = false,
const ArrayLengthFromUniformOptions& array_length_from_uniform = {});
/// Implementation class for HLSL generator

View File

@@ -78,9 +78,11 @@ class TestHelperBase : public BODY, public ProgramBuilder {
<< formatter.format(program->Diagnostics());
}();
auto sanitized_result = Sanitize(
program.get(), options.root_constant_binding_point,
options.disable_workgroup_init, options.array_length_from_uniform);
auto sanitized_result =
Sanitize(program.get(), options.root_constant_binding_point,
options.disable_workgroup_init,
options.generate_external_texture_bindings,
options.array_length_from_uniform);
[&]() {
ASSERT_TRUE(sanitized_result.program.IsValid())
<< formatter.format(sanitized_result.program.Diagnostics());

View File

@@ -38,6 +38,7 @@ Result Generate(const Program* program, const Options& options) {
auto sanitized_result = Sanitize(
program, options.buffer_size_ubo_index, options.fixed_sample_mask,
options.emit_vertex_point_size, options.disable_workgroup_init,
options.generate_external_texture_bindings,
options.array_length_from_uniform);
if (!sanitized_result.program.IsValid()) {
result.success = false;

View File

@@ -61,6 +61,9 @@ struct Options {
/// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false;
/// Set to 'true' to generates binding mappings for external textures
bool generate_external_texture_bindings = false;
/// Options used to specify a mapping of binding points to indices into a UBO
/// from which to load buffer sizes.
ArrayLengthFromUniformOptions array_length_from_uniform = {};

View File

@@ -77,6 +77,7 @@
#include "src/tint/utils/map.h"
#include "src/tint/utils/scoped_assignment.h"
#include "src/tint/writer/float_to_string.h"
#include "src/tint/writer/generate_external_texture_bindings.h"
namespace tint {
namespace writer {
@@ -113,6 +114,7 @@ class ScopedBitCast {
private:
std::ostream& s;
};
} // namespace
SanitizedResult::SanitizedResult() = default;
@@ -125,6 +127,7 @@ SanitizedResult Sanitize(
uint32_t fixed_sample_mask,
bool emit_vertex_point_size,
bool disable_workgroup_init,
bool generate_external_texture_bindings,
const ArrayLengthFromUniformOptions& array_length_from_uniform) {
transform::Manager manager;
transform::DataMap data;
@@ -167,6 +170,13 @@ SanitizedResult Sanitize(
transform::CanonicalizeEntryPointIO::ShaderStyle::kMsl, fixed_sample_mask,
emit_vertex_point_size);
if (generate_external_texture_bindings) {
auto new_bindings_map = GenerateExternalTextureBindings(in);
data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
new_bindings_map);
}
manager.Add<transform::MultiplanarExternalTexture>();
manager.Add<transform::Unshadow>();
if (!disable_workgroup_init) {

View File

@@ -84,6 +84,7 @@ SanitizedResult Sanitize(
uint32_t fixed_sample_mask = 0xFFFFFFFF,
bool emit_vertex_point_size = false,
bool disable_workgroup_init = false,
bool generate_external_texture_bindings = false,
const ArrayLengthFromUniformOptions& array_length_from_uniform = {});
/// Implementation class for MSL generator

View File

@@ -79,6 +79,7 @@ class TestHelperBase : public BASE, public ProgramBuilder {
auto result = Sanitize(
program.get(), options.buffer_size_ubo_index, options.fixed_sample_mask,
options.emit_vertex_point_size, options.disable_workgroup_init,
options.generate_external_texture_bindings,
options.array_length_from_uniform);
[&]() {
ASSERT_TRUE(result.program.IsValid())

View File

@@ -60,6 +60,7 @@
#include "src/tint/utils/defer.h"
#include "src/tint/utils/map.h"
#include "src/tint/writer/append_vector.h"
#include "src/tint/writer/generate_external_texture_bindings.h"
namespace tint {
namespace writer {
@@ -258,7 +259,8 @@ const sem::Type* ElementTypeOf(const sem::Type* ty) {
SanitizedResult Sanitize(const Program* in,
bool emit_vertex_point_size,
bool disable_workgroup_init) {
bool disable_workgroup_init,
bool generate_external_texture_bindings) {
transform::Manager manager;
transform::DataMap data;
@@ -275,6 +277,13 @@ SanitizedResult Sanitize(const Program* in,
manager.Add<transform::BuiltinPolyfill>();
}
if (generate_external_texture_bindings) {
auto new_bindings_map = GenerateExternalTextureBindings(in);
data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
new_bindings_map);
}
manager.Add<transform::MultiplanarExternalTexture>();
manager.Add<transform::Unshadow>();
if (!disable_workgroup_init) {
manager.Add<transform::ZeroInitWorkgroupMemory>();

View File

@@ -65,7 +65,8 @@ struct SanitizedResult {
/// @returns the sanitized program and any supplementary information
SanitizedResult Sanitize(const Program* program,
bool emit_vertex_point_size = false,
bool disable_workgroup_init = false);
bool disable_workgroup_init = false,
bool generate_external_texture_bindings = false);
/// Builder class to create SPIR-V instructions from a module.
class Builder {

View File

@@ -32,7 +32,8 @@ Result Generate(const Program* program, const Options& options) {
options.disable_workgroup_init ||
options.use_zero_initialize_workgroup_memory_extension;
auto sanitized_result = Sanitize(program, options.emit_vertex_point_size,
disable_workgroup_init_in_sanitizer);
disable_workgroup_init_in_sanitizer,
options.generate_external_texture_bindings);
if (!sanitized_result.program.IsValid()) {
result.success = false;
result.error = sanitized_result.program.Diagnostics().str();

View File

@@ -42,6 +42,9 @@ struct Options {
/// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false;
/// Set to 'true' to generates binding mappings for external textures
bool generate_external_texture_bindings = false;
/// Set to `true` to initialize workgroup memory with OpConstantNull when
/// VK_KHR_zero_initialize_workgroup_memory is enabled.
bool use_zero_initialize_workgroup_memory_extension = false;