Merge pull request #3039 from ReinUsesLisp/cleanup-samplers

shader/node: Unpack bindless texture encoding
This commit is contained in:
Rodrigo Locatti 2019-11-06 04:54:11 +00:00 committed by GitHub
commit 654b77d2ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 118 additions and 144 deletions

View file

@ -143,39 +143,37 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
}
Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) {
const auto offset{static_cast<std::size_t>(image.index.Value())};
if (const auto existing_image = TryUseExistingImage(offset, type)) {
return *existing_image;
const auto offset = static_cast<u32>(image.index.Value());
const auto it =
std::find_if(std::begin(used_images), std::end(used_images),
[offset](const Image& entry) { return entry.GetOffset() == offset; });
if (it != std::end(used_images)) {
ASSERT(!it->IsBindless() && it->GetType() == it->GetType());
return *it;
}
const std::size_t next_index{used_images.size()};
return used_images.emplace(offset, Image{offset, next_index, type}).first->second;
const auto next_index = static_cast<u32>(used_images.size());
return used_images.emplace_back(next_index, offset, type);
}
Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) {
const Node image_register{GetRegister(reg)};
const auto [base_image, cbuf_index, cbuf_offset]{
TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))};
const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)};
const Node image_register = GetRegister(reg);
const auto [base_image, buffer, offset] =
TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()));
if (const auto image = TryUseExistingImage(cbuf_key, type)) {
return *image;
const auto it =
std::find_if(std::begin(used_images), std::end(used_images),
[buffer = buffer, offset = offset](const Image& entry) {
return entry.GetBuffer() == buffer && entry.GetOffset() == offset;
});
if (it != std::end(used_images)) {
ASSERT(it->IsBindless() && it->GetType() == it->GetType());
return *it;
}
const std::size_t next_index{used_images.size()};
return used_images.emplace(cbuf_key, Image{cbuf_index, cbuf_offset, next_index, type})
.first->second;
}
Image* ShaderIR::TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type) {
auto it = used_images.find(offset);
if (it == used_images.end()) {
return nullptr;
}
auto& image = it->second;
ASSERT(image.GetType() == type);
return &image;
const auto next_index = static_cast<u32>(used_images.size());
return used_images.emplace_back(next_index, offset, buffer, type);
}
} // namespace VideoCommon::Shader

View file

@ -262,7 +262,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
break;
}
case OpCode::Id::TLDS: {
const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()};
const TextureType texture_type{instr.tlds.GetTextureType()};
const bool is_array{instr.tlds.IsArrayTexture()};
UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI),
@ -293,77 +293,80 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
std::optional<SamplerInfo> sampler_info) {
const auto offset = static_cast<u32>(sampler.index.Value());
Tegra::Shader::TextureType type;
TextureType type;
bool is_array;
bool is_shadow;
if (sampler_info) {
type = sampler_info->type;
is_array = sampler_info->is_array;
is_shadow = sampler_info->is_shadow;
} else if (auto sampler = locker.ObtainBoundSampler(offset); sampler) {
} else if (const auto sampler = locker.ObtainBoundSampler(offset)) {
type = sampler->texture_type.Value();
is_array = sampler->is_array.Value() != 0;
is_shadow = sampler->is_shadow.Value() != 0;
} else {
type = Tegra::Shader::TextureType::Texture2D;
LOG_WARNING(HW_GPU, "Unknown sampler info");
type = TextureType::Texture2D;
is_array = false;
is_shadow = false;
}
// If this sampler has already been used, return the existing mapping.
const auto itr =
const auto it =
std::find_if(used_samplers.begin(), used_samplers.end(),
[&](const Sampler& entry) { return entry.GetOffset() == offset; });
if (itr != used_samplers.end()) {
ASSERT(itr->GetType() == type && itr->IsArray() == is_array &&
itr->IsShadow() == is_shadow);
return *itr;
[offset](const Sampler& entry) { return entry.GetOffset() == offset; });
if (it != used_samplers.end()) {
ASSERT(!it->IsBindless() && it->GetType() == type && it->IsArray() == is_array &&
it->IsShadow() == is_shadow);
return *it;
}
// Otherwise create a new mapping for this sampler
const std::size_t next_index = used_samplers.size();
const Sampler entry{offset, next_index, type, is_array, is_shadow};
return *used_samplers.emplace(entry).first;
} // namespace VideoCommon::Shader
const auto next_index = static_cast<u32>(used_samplers.size());
return used_samplers.emplace_back(Sampler(next_index, offset, type, is_array, is_shadow));
}
const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
std::optional<SamplerInfo> sampler_info) {
const Node sampler_register = GetRegister(reg);
const auto [base_sampler, cbuf_index, cbuf_offset] =
const auto [base_sampler, buffer, offset] =
TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
ASSERT(base_sampler != nullptr);
const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset);
Tegra::Shader::TextureType type;
TextureType type;
bool is_array;
bool is_shadow;
if (sampler_info) {
type = sampler_info->type;
is_array = sampler_info->is_array;
is_shadow = sampler_info->is_shadow;
} else if (auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); sampler) {
} else if (const auto sampler = locker.ObtainBindlessSampler(buffer, offset)) {
type = sampler->texture_type.Value();
is_array = sampler->is_array.Value() != 0;
is_shadow = sampler->is_shadow.Value() != 0;
} else {
type = Tegra::Shader::TextureType::Texture2D;
LOG_WARNING(HW_GPU, "Unknown sampler info");
type = TextureType::Texture2D;
is_array = false;
is_shadow = false;
}
// If this sampler has already been used, return the existing mapping.
const auto itr =
const auto it =
std::find_if(used_samplers.begin(), used_samplers.end(),
[&](const Sampler& entry) { return entry.GetOffset() == cbuf_key; });
if (itr != used_samplers.end()) {
ASSERT(itr->GetType() == type && itr->IsArray() == is_array &&
itr->IsShadow() == is_shadow);
return *itr;
[buffer = buffer, offset = offset](const Sampler& entry) {
return entry.GetBuffer() == buffer && entry.GetOffset() == offset;
});
if (it != used_samplers.end()) {
ASSERT(it->IsBindless() && it->GetType() == type && it->IsArray() == is_array &&
it->IsShadow() == is_shadow);
return *it;
}
// Otherwise create a new mapping for this sampler
const std::size_t next_index = used_samplers.size();
const Sampler entry{cbuf_index, cbuf_offset, next_index, type, is_array, is_shadow};
return *used_samplers.emplace(entry).first;
const auto next_index = static_cast<u32>(used_samplers.size());
return used_samplers.emplace_back(
Sampler(next_index, offset, buffer, type, is_array, is_shadow));
}
void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) {