[SPIR-V] Texture fetch instructions

This commit is contained in:
Triang3l
2022-06-09 21:42:16 +03:00
parent f875a8d887
commit 1a22216e44
5 changed files with 2363 additions and 18 deletions

View File

@@ -30,6 +30,7 @@ SpirvShaderTranslator::Features::Features(bool all)
max_storage_buffer_range(all ? UINT32_MAX : (128 * 1024 * 1024)),
clip_distance(all),
cull_distance(all),
image_view_format_swizzle(all),
signed_zero_inf_nan_preserve_float32(all),
denorm_flush_to_zero_float32(all) {}
@@ -51,6 +52,15 @@ SpirvShaderTranslator::Features::Features(
} else {
spirv_version = spv::Spv_1_0;
}
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
device_portability_subset_features =
provider.device_portability_subset_features();
if (device_portability_subset_features) {
image_view_format_swizzle =
bool(device_portability_subset_features->imageViewFormatSwizzle);
} else {
image_view_format_swizzle = true;
}
if (spirv_version >= spv::Spv_1_4 ||
device_extensions.khr_shader_float_controls) {
const VkPhysicalDeviceFloatControlsPropertiesKHR&
@@ -198,6 +208,14 @@ void SpirvShaderTranslator::StartTranslation() {
size_t offset;
spv::Id type;
};
spv::Id type_uint4_array_2 = builder_->makeArrayType(
type_uint4_, builder_->makeUintConstant(2), sizeof(uint32_t) * 4);
builder_->addDecoration(type_uint4_array_2, spv::DecorationArrayStride,
sizeof(uint32_t) * 4);
spv::Id type_uint4_array_4 = builder_->makeArrayType(
type_uint4_, builder_->makeUintConstant(4), sizeof(uint32_t) * 4);
builder_->addDecoration(type_uint4_array_4, spv::DecorationArrayStride,
sizeof(uint32_t) * 4);
const SystemConstant system_constants[] = {
{"flags", offsetof(SystemConstants, flags), type_uint_},
{"vertex_index_endian", offsetof(SystemConstants, vertex_index_endian),
@@ -206,6 +224,10 @@ void SpirvShaderTranslator::StartTranslation() {
type_int_},
{"ndc_scale", offsetof(SystemConstants, ndc_scale), type_float3_},
{"ndc_offset", offsetof(SystemConstants, ndc_offset), type_float3_},
{"texture_swizzled_signs",
offsetof(SystemConstants, texture_swizzled_signs), type_uint4_array_2},
{"texture_swizzles", offsetof(SystemConstants, texture_swizzles),
type_uint4_array_4},
};
id_vector_temp_.clear();
id_vector_temp_.reserve(xe::countof(system_constants));
@@ -401,6 +423,15 @@ void SpirvShaderTranslator::StartTranslation() {
var_main_vfetch_address_ = builder_->createVariable(
spv::NoPrecision, spv::StorageClassFunction, type_int_,
"xe_var_vfetch_address", const_int_0_);
var_main_tfetch_lod_ = builder_->createVariable(
spv::NoPrecision, spv::StorageClassFunction, type_float_,
"xe_var_tfetch_lod", const_float_0_);
var_main_tfetch_gradients_h_ = builder_->createVariable(
spv::NoPrecision, spv::StorageClassFunction, type_float3_,
"xe_var_tfetch_gradients_h", const_float3_0_);
var_main_tfetch_gradients_v_ = builder_->createVariable(
spv::NoPrecision, spv::StorageClassFunction, type_float3_,
"xe_var_tfetch_gradients_v", const_float3_0_);
uint32_t register_array_size = register_count();
if (register_array_size) {
id_vector_temp_.clear();
@@ -945,6 +976,29 @@ void SpirvShaderTranslator::ProcessJumpInstruction(
builder_->createBranch(main_loop_continue_);
}
spv::Id SpirvShaderTranslator::SpirvSmearScalarResultOrConstant(
spv::Id scalar, spv::Id vector_type) {
bool is_constant = builder_->isConstant(scalar);
bool is_spec_constant = builder_->isSpecConstant(scalar);
if (!is_constant && !is_spec_constant) {
return builder_->smearScalar(spv::NoPrecision, scalar, vector_type);
}
assert_true(builder_->getTypeClass(builder_->getTypeId(scalar)) ==
builder_->getTypeClass(builder_->getScalarTypeId(vector_type)));
if (!builder_->isVectorType(vector_type)) {
assert_true(builder_->isScalarType(vector_type));
return scalar;
}
int num_components = builder_->getNumTypeComponents(vector_type);
id_vector_temp_util_.clear();
id_vector_temp_util_.reserve(size_t(num_components));
for (int i = 0; i < num_components; ++i) {
id_vector_temp_util_.push_back(scalar);
}
return builder_->makeCompositeConstant(vector_type, id_vector_temp_util_,
is_spec_constant);
}
void SpirvShaderTranslator::EnsureBuildPointAvailable() {
if (!builder_->getBuildPoint()->isTerminated()) {
return;
@@ -2049,5 +2103,188 @@ spv::Id SpirvShaderTranslator::LoadUint32FromSharedMemory(
return value_phi_result;
}
spv::Id SpirvShaderTranslator::PWLGammaToLinear(spv::Id gamma,
bool gamma_pre_saturated) {
spv::Id value_type = builder_->getTypeId(gamma);
assert_true(builder_->isFloatType(builder_->getScalarTypeId(value_type)));
bool is_vector = builder_->isVectorType(value_type);
assert_true(is_vector || builder_->isFloatType(value_type));
int num_components = builder_->getNumTypeComponents(value_type);
assert_true(num_components < 4);
spv::Id bool_type = type_bool_vectors_[num_components - 1];
spv::Id const_vector_0 = const_float_vectors_0_[num_components - 1];
spv::Id const_vector_1 = SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(1.0f), value_type);
if (!gamma_pre_saturated) {
// Saturate, flushing NaN to 0.
id_vector_temp_.clear();
id_vector_temp_.reserve(3);
id_vector_temp_.push_back(gamma);
id_vector_temp_.push_back(const_vector_0);
id_vector_temp_.push_back(const_vector_1);
gamma = builder_->createBuiltinCall(value_type, ext_inst_glsl_std_450_,
GLSLstd450NClamp, id_vector_temp_);
}
spv::Id is_piece_at_least_3 = builder_->createBinOp(
spv::OpFOrdGreaterThanEqual, bool_type, gamma,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(192.0f / 255.0f), value_type));
spv::Id scale_3_or_2 = builder_->createTriOp(
spv::OpSelect, value_type, is_piece_at_least_3,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(8.0f / 1024.0f), value_type),
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(4.0f / 1024.0f), value_type));
spv::Id offset_3_or_2 = builder_->createTriOp(
spv::OpSelect, value_type, is_piece_at_least_3,
SpirvSmearScalarResultOrConstant(builder_->makeFloatConstant(-1024.0f),
value_type),
SpirvSmearScalarResultOrConstant(builder_->makeFloatConstant(-256.0f),
value_type));
spv::Id is_piece_at_least_1 = builder_->createBinOp(
spv::OpFOrdGreaterThanEqual, bool_type, gamma,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(64.0f / 255.0f), value_type));
spv::Id scale_1_or_0 = builder_->createTriOp(
spv::OpSelect, value_type, is_piece_at_least_1,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(2.0f / 1024.0f), value_type),
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(1.0f / 1024.0f), value_type));
spv::Id offset_1_or_0 = builder_->createTriOp(
spv::OpSelect, value_type, is_piece_at_least_1,
SpirvSmearScalarResultOrConstant(builder_->makeFloatConstant(-64.0f),
value_type),
const_vector_0);
spv::Id is_piece_at_least_2 = builder_->createBinOp(
spv::OpFOrdGreaterThanEqual, bool_type, gamma,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(96.0f / 255.0f), value_type));
spv::Id scale =
builder_->createTriOp(spv::OpSelect, value_type, is_piece_at_least_2,
scale_3_or_2, scale_1_or_0);
spv::Id offset =
builder_->createTriOp(spv::OpSelect, value_type, is_piece_at_least_2,
offset_3_or_2, offset_1_or_0);
spv::Op value_times_scalar_opcode =
is_vector ? spv::OpVectorTimesScalar : spv::OpFMul;
// linear = gamma * (255.0f * 1024.0f) * scale + offset
spv::Id linear =
builder_->createBinOp(value_times_scalar_opcode, value_type, gamma,
builder_->makeFloatConstant(255.0f * 1024.0f));
builder_->addDecoration(linear, spv::DecorationNoContraction);
linear = builder_->createBinOp(spv::OpFMul, value_type, linear, scale);
builder_->addDecoration(linear, spv::DecorationNoContraction);
linear = builder_->createBinOp(spv::OpFAdd, value_type, linear, offset);
builder_->addDecoration(linear, spv::DecorationNoContraction);
// linear += trunc(linear * scale)
spv::Id linear_integer_term =
builder_->createBinOp(spv::OpFMul, value_type, linear, scale);
builder_->addDecoration(linear_integer_term, spv::DecorationNoContraction);
id_vector_temp_.clear();
id_vector_temp_.push_back(linear_integer_term);
linear_integer_term = builder_->createBuiltinCall(
value_type, ext_inst_glsl_std_450_, GLSLstd450Trunc, id_vector_temp_);
linear = builder_->createBinOp(spv::OpFAdd, value_type, linear,
linear_integer_term);
builder_->addDecoration(linear, spv::DecorationNoContraction);
// linear *= 1.0f / 1023.0f
linear = builder_->createBinOp(value_times_scalar_opcode, value_type, linear,
builder_->makeFloatConstant(1.0f / 1023.0f));
builder_->addDecoration(linear, spv::DecorationNoContraction);
return linear;
}
spv::Id SpirvShaderTranslator::LinearToPWLGamma(spv::Id linear,
bool linear_pre_saturated) {
spv::Id value_type = builder_->getTypeId(linear);
assert_true(builder_->isFloatType(builder_->getScalarTypeId(value_type)));
bool is_vector = builder_->isVectorType(value_type);
assert_true(is_vector || builder_->isFloatType(value_type));
int num_components = builder_->getNumTypeComponents(value_type);
assert_true(num_components < 4);
spv::Id bool_type = type_bool_vectors_[num_components - 1];
spv::Id const_vector_0 = const_float_vectors_0_[num_components - 1];
spv::Id const_vector_1 = SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(1.0f), value_type);
if (!linear_pre_saturated) {
// Saturate, flushing NaN to 0.
id_vector_temp_.clear();
id_vector_temp_.reserve(3);
id_vector_temp_.push_back(linear);
id_vector_temp_.push_back(const_vector_0);
id_vector_temp_.push_back(const_vector_1);
linear = builder_->createBuiltinCall(value_type, ext_inst_glsl_std_450_,
GLSLstd450NClamp, id_vector_temp_);
}
spv::Id is_piece_at_least_3 = builder_->createBinOp(
spv::OpFOrdGreaterThanEqual, bool_type, linear,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(512.0f / 1023.0f), value_type));
spv::Id scale_3_or_2 = builder_->createTriOp(
spv::OpSelect, value_type, is_piece_at_least_3,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(1023.0f / 8.0f), value_type),
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(1023.0f / 4.0f), value_type));
spv::Id offset_3_or_2 = builder_->createTriOp(
spv::OpSelect, value_type, is_piece_at_least_3,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(128.0f / 255.0f), value_type),
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(64.0f / 255.0f), value_type));
spv::Id is_piece_at_least_1 = builder_->createBinOp(
spv::OpFOrdGreaterThanEqual, bool_type, linear,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(64.0f / 1023.0f), value_type));
spv::Id scale_1_or_0 = builder_->createTriOp(
spv::OpSelect, value_type, is_piece_at_least_1,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(1023.0f / 2.0f), value_type),
SpirvSmearScalarResultOrConstant(builder_->makeFloatConstant(1023.0f),
value_type));
spv::Id offset_1_or_0 = builder_->createTriOp(
spv::OpSelect, value_type, is_piece_at_least_1,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(32.0f / 255.0f), value_type),
const_vector_0);
spv::Id is_piece_at_least_2 = builder_->createBinOp(
spv::OpFOrdGreaterThanEqual, bool_type, linear,
SpirvSmearScalarResultOrConstant(
builder_->makeFloatConstant(128.0f / 1023.0f), value_type));
spv::Id scale =
builder_->createTriOp(spv::OpSelect, value_type, is_piece_at_least_2,
scale_3_or_2, scale_1_or_0);
spv::Id offset =
builder_->createTriOp(spv::OpSelect, value_type, is_piece_at_least_2,
offset_3_or_2, offset_1_or_0);
// gamma = trunc(linear * scale) * (1.0f / 255.0f) + offset
spv::Id gamma = builder_->createBinOp(spv::OpFMul, value_type, linear, scale);
builder_->addDecoration(gamma, spv::DecorationNoContraction);
id_vector_temp_.clear();
id_vector_temp_.push_back(gamma);
gamma = builder_->createBuiltinCall(value_type, ext_inst_glsl_std_450_,
GLSLstd450Trunc, id_vector_temp_);
gamma = builder_->createBinOp(
is_vector ? spv::OpVectorTimesScalar : spv::OpFMul, value_type, gamma,
builder_->makeFloatConstant(1.0f / 255.0f));
builder_->addDecoration(gamma, spv::DecorationNoContraction);
gamma = builder_->createBinOp(spv::OpFAdd, value_type, gamma, offset);
builder_->addDecoration(gamma, spv::DecorationNoContraction);
return gamma;
}
} // namespace gpu
} // namespace xe