[SPIR-V] Texture fetch instructions
This commit is contained in:
parent
f875a8d887
commit
1a22216e44
|
@ -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
|
||||
|
|
|
@ -84,6 +84,16 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
|
||||
float ndc_offset[3];
|
||||
uint32_t padding_ndc_offset;
|
||||
|
||||
// Each byte contains post-swizzle TextureSign values for each of the needed
|
||||
// components of each of the 32 used texture fetch constants.
|
||||
uint32_t texture_swizzled_signs[8];
|
||||
|
||||
// If the imageViewFormatSwizzle portability subset is not supported, the
|
||||
// component swizzle (taking both guest and host swizzles into account) to
|
||||
// apply to the result directly in the shader code. In each uint32_t,
|
||||
// swizzles for 2 texture fetch constants (in bits 0:11 and 12:23).
|
||||
uint32_t texture_swizzles[16];
|
||||
};
|
||||
|
||||
// The minimum limit for maxPerStageDescriptorStorageBuffers is 4, and for
|
||||
|
@ -151,6 +161,7 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
uint32_t max_storage_buffer_range;
|
||||
bool clip_distance;
|
||||
bool cull_distance;
|
||||
bool image_view_format_swizzle;
|
||||
bool signed_zero_inf_nan_preserve_float32;
|
||||
bool denorm_flush_to_zero_float32;
|
||||
};
|
||||
|
@ -244,7 +255,6 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
xenos::FetchOpDimension dimension;
|
||||
bool is_signed;
|
||||
|
||||
spv::Id type;
|
||||
spv::Id variable;
|
||||
};
|
||||
|
||||
|
@ -259,6 +269,7 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
};
|
||||
|
||||
// Builder helpers.
|
||||
spv::Id SpirvSmearScalarResultOrConstant(spv::Id scalar, spv::Id vector_type);
|
||||
void SpirvCreateSelectionMerge(
|
||||
spv::Id merge_block_id, spv::SelectionControlMask selection_control_mask =
|
||||
spv::SelectionControlMaskNone) {
|
||||
|
@ -379,6 +390,10 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
|
||||
spv::Id LoadUint32FromSharedMemory(spv::Id address_dwords_int);
|
||||
|
||||
// The source may be a floating-point scalar or a vector.
|
||||
spv::Id PWLGammaToLinear(spv::Id gamma, bool gamma_pre_saturated);
|
||||
spv::Id LinearToPWLGamma(spv::Id linear, bool linear_pre_saturated);
|
||||
|
||||
size_t FindOrAddTextureBinding(uint32_t fetch_constant,
|
||||
xenos::FetchOpDimension dimension,
|
||||
bool is_signed);
|
||||
|
@ -387,6 +402,24 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
xenos::TextureFilter min_filter,
|
||||
xenos::TextureFilter mip_filter,
|
||||
xenos::AnisoFilter aniso_filter);
|
||||
// `texture_parameters` need to be set up except for `sampler`, which will be
|
||||
// set internally, optionally doing linear interpolation between the an
|
||||
// existing value and the new one (the result location may be the same as for
|
||||
// the first lerp endpoint, but not across signedness).
|
||||
void SampleTexture(spv::Builder::TextureParameters& texture_parameters,
|
||||
spv::ImageOperandsMask image_operands_mask,
|
||||
spv::Id image_unsigned, spv::Id image_signed,
|
||||
spv::Id sampler, spv::Id is_all_signed,
|
||||
spv::Id is_any_signed, spv::Id& result_unsigned_out,
|
||||
spv::Id& result_signed_out,
|
||||
spv::Id lerp_factor = spv::NoResult,
|
||||
spv::Id lerp_first_unsigned = spv::NoResult,
|
||||
spv::Id lerp_first_signed = spv::NoResult);
|
||||
// `texture_parameters` need to be set up except for `sampler`, which will be
|
||||
// set internally.
|
||||
spv::Id QueryTextureLod(spv::Builder::TextureParameters& texture_parameters,
|
||||
spv::Id image_unsigned, spv::Id image_signed,
|
||||
spv::Id sampler, spv::Id is_all_signed);
|
||||
|
||||
Features features_;
|
||||
|
||||
|
@ -473,6 +506,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
kSystemConstantIndexVertexBaseIndex,
|
||||
kSystemConstantNdcScale,
|
||||
kSystemConstantNdcOffset,
|
||||
kSystemConstantTextureSwizzledSigns,
|
||||
kSystemConstantTextureSwizzles,
|
||||
};
|
||||
spv::Id uniform_system_constants_;
|
||||
spv::Id uniform_float_constants_;
|
||||
|
@ -522,6 +557,11 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
// `base + index * stride` in dwords from the last vfetch_full as it may be
|
||||
// needed by vfetch_mini - int.
|
||||
spv::Id var_main_vfetch_address_;
|
||||
// float.
|
||||
spv::Id var_main_tfetch_lod_;
|
||||
// float3.
|
||||
spv::Id var_main_tfetch_gradients_h_;
|
||||
spv::Id var_main_tfetch_gradients_v_;
|
||||
// float4[register_count()].
|
||||
spv::Id var_main_registers_;
|
||||
// VS only - float3 (special exports).
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1774,7 +1774,7 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
|
|||
|
||||
// Update system constants before uploading them.
|
||||
UpdateSystemConstantValues(primitive_processing_result.host_index_endian,
|
||||
viewport_info);
|
||||
viewport_info, used_texture_mask);
|
||||
|
||||
// Update uniform buffers and descriptor sets after binding the pipeline with
|
||||
// the new layout.
|
||||
|
@ -2682,7 +2682,8 @@ void VulkanCommandProcessor::UpdateDynamicState(
|
|||
}
|
||||
|
||||
void VulkanCommandProcessor::UpdateSystemConstantValues(
|
||||
xenos::Endian index_endian, const draw_util::ViewportInfo& viewport_info) {
|
||||
xenos::Endian index_endian, const draw_util::ViewportInfo& viewport_info,
|
||||
uint32_t used_texture_mask) {
|
||||
#if XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
|
||||
|
@ -2731,6 +2732,55 @@ void VulkanCommandProcessor::UpdateSystemConstantValues(
|
|||
system_constants_.ndc_offset[i] = viewport_info.ndc_offset[i];
|
||||
}
|
||||
|
||||
// Texture signedness / gamma.
|
||||
{
|
||||
uint32_t textures_remaining = used_texture_mask;
|
||||
uint32_t texture_index;
|
||||
while (xe::bit_scan_forward(textures_remaining, &texture_index)) {
|
||||
textures_remaining &= ~(UINT32_C(1) << texture_index);
|
||||
uint32_t& texture_signs_uint =
|
||||
system_constants_.texture_swizzled_signs[texture_index >> 2];
|
||||
uint32_t texture_signs_shift = 8 * (texture_index & 3);
|
||||
uint8_t texture_signs =
|
||||
texture_cache_->GetActiveTextureSwizzledSigns(texture_index);
|
||||
uint32_t texture_signs_shifted = uint32_t(texture_signs)
|
||||
<< texture_signs_shift;
|
||||
uint32_t texture_signs_mask = (UINT32_C(1 << 8) - 1)
|
||||
<< texture_signs_shift;
|
||||
dirty |=
|
||||
(texture_signs_uint & texture_signs_mask) != texture_signs_shifted;
|
||||
texture_signs_uint =
|
||||
(texture_signs_uint & ~texture_signs_mask) | texture_signs_shifted;
|
||||
}
|
||||
}
|
||||
|
||||
// Texture host swizzle in the shader.
|
||||
const ui::vulkan::VulkanProvider& provider = GetVulkanProvider();
|
||||
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
|
||||
device_portability_subset_features =
|
||||
provider.device_portability_subset_features();
|
||||
if (device_portability_subset_features &&
|
||||
!device_portability_subset_features->imageViewFormatSwizzle) {
|
||||
uint32_t textures_remaining = used_texture_mask;
|
||||
uint32_t texture_index;
|
||||
while (xe::bit_scan_forward(textures_remaining, &texture_index)) {
|
||||
textures_remaining &= ~(UINT32_C(1) << texture_index);
|
||||
uint32_t& texture_swizzles_uint =
|
||||
system_constants_.texture_swizzles[texture_index >> 1];
|
||||
uint32_t texture_swizzle_shift = 12 * (texture_index & 1);
|
||||
uint32_t texture_swizzle =
|
||||
texture_cache_->GetActiveTextureHostSwizzle(texture_index);
|
||||
uint32_t texture_swizzle_shifted = uint32_t(texture_swizzle)
|
||||
<< texture_swizzle_shift;
|
||||
uint32_t texture_swizzle_mask = (UINT32_C(1 << 12) - 1)
|
||||
<< texture_swizzle_shift;
|
||||
dirty |= (texture_swizzles_uint & texture_swizzle_mask) !=
|
||||
texture_swizzle_shifted;
|
||||
texture_swizzles_uint = (texture_swizzles_uint & ~texture_swizzle_mask) |
|
||||
texture_swizzle_shifted;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
current_graphics_descriptor_set_values_up_to_date_ &=
|
||||
~(UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetSystemConstants);
|
||||
|
|
|
@ -432,7 +432,8 @@ class VulkanCommandProcessor : public CommandProcessor {
|
|||
bool primitive_polygonal,
|
||||
reg::RB_DEPTHCONTROL normalized_depth_control);
|
||||
void UpdateSystemConstantValues(xenos::Endian index_endian,
|
||||
const draw_util::ViewportInfo& viewport_info);
|
||||
const draw_util::ViewportInfo& viewport_info,
|
||||
uint32_t used_texture_mask);
|
||||
bool UpdateBindings(const VulkanShader* vertex_shader,
|
||||
const VulkanShader* pixel_shader);
|
||||
// Allocates a descriptor set and fills the VkWriteDescriptorSet structure.
|
||||
|
|
Loading…
Reference in New Issue