gl_shader_decompiler: Use uint for images and fix SUATOM

In the process remove implementation of SUATOM.MIN and SUATOM.MAX as
these require a distinction between U32 and S32. These have to be
implemented with imageCompSwap loop.
This commit is contained in:
ReinUsesLisp 2019-09-18 01:50:40 -03:00
parent 675f23aedc
commit 44000971e2
No known key found for this signature in database
GPG key ID: 2DFC508897B39CFE
7 changed files with 93 additions and 188 deletions

View file

@ -716,36 +716,20 @@ private:
const char* image_type = [&] {
switch (image.GetType()) {
case Tegra::Shader::ImageType::Texture1D:
return "image1D";
return "1D";
case Tegra::Shader::ImageType::TextureBuffer:
return "imageBuffer";
return "Buffer";
case Tegra::Shader::ImageType::Texture1DArray:
return "image1DArray";
return "1DArray";
case Tegra::Shader::ImageType::Texture2D:
return "image2D";
return "2D";
case Tegra::Shader::ImageType::Texture2DArray:
return "image2DArray";
return "2DArray";
case Tegra::Shader::ImageType::Texture3D:
return "image3D";
return "3D";
default:
UNREACHABLE();
return "image1D";
}
}();
const auto [type_prefix, format] = [&]() -> std::pair<const char*, const char*> {
if (!image.IsSizeKnown()) {
return {"", ""};
}
switch (image.GetSize()) {
case Tegra::Shader::ImageAtomicSize::U32:
return {"u", "r32ui, "};
case Tegra::Shader::ImageAtomicSize::S32:
return {"i", "r32i, "};
default:
UNIMPLEMENTED_MSG("Unimplemented atomic size={}",
static_cast<u32>(image.GetSize()));
return {"", ""};
return "1D";
}
}();
@ -756,8 +740,12 @@ private:
qualifier += " writeonly";
}
code.AddLine("layout (binding = IMAGE_BINDING_{}) {} uniform "
"{} {};",
std::string format;
if (image.IsAtomic()) {
format = "r32ui, ";
}
code.AddLine("layout ({}binding = IMAGE_BINDING_{}) {} uniform uimage{} {};", format,
image.GetIndex(), qualifier, image_type, GetImage(image));
}
if (!images.empty()) {
@ -1225,28 +1213,13 @@ private:
}
std::string BuildImageValues(Operation operation) {
constexpr std::array constructors{"uint", "uvec2", "uvec3", "uvec4"};
const auto meta{std::get<MetaImage>(operation.GetMeta())};
const auto [constructors, type] = [&]() -> std::pair<std::array<const char*, 4>, Type> {
constexpr std::array float_constructors{"float", "vec2", "vec3", "vec4"};
if (!meta.image.IsSizeKnown()) {
return {float_constructors, Type::Float};
}
switch (meta.image.GetSize()) {
case Tegra::Shader::ImageAtomicSize::U32:
return {{"uint", "uvec2", "uvec3", "uvec4"}, Type::Uint};
case Tegra::Shader::ImageAtomicSize::S32:
return {{"int", "ivec2", "ivec3", "ivec4"}, Type::Uint};
default:
UNIMPLEMENTED_MSG("Unimplemented image size={}",
static_cast<u32>(meta.image.GetSize()));
return {float_constructors, Type::Float};
}
}();
const std::size_t values_count{meta.values.size()};
std::string expr = fmt::format("{}(", constructors.at(values_count - 1));
for (std::size_t i = 0; i < values_count; ++i) {
expr += Visit(meta.values.at(i)).As(type);
expr += Visit(meta.values.at(i)).AsUint();
if (i + 1 < values_count) {
expr += ", ";
}
@ -1255,29 +1228,6 @@ private:
return expr;
}
Expression AtomicImage(Operation operation, const char* opname) {
constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
const auto meta{std::get<MetaImage>(operation.GetMeta())};
ASSERT(meta.values.size() == 1);
ASSERT(meta.image.IsSizeKnown());
const auto type = [&]() {
switch (const auto size = meta.image.GetSize()) {
case Tegra::Shader::ImageAtomicSize::U32:
return Type::Uint;
case Tegra::Shader::ImageAtomicSize::S32:
return Type::Int;
default:
UNIMPLEMENTED_MSG("Unimplemented image size={}", static_cast<u32>(size));
return Type::Uint;
}
}();
return {fmt::format("{}({}, {}, {})", opname, GetImage(meta.image),
BuildIntegerCoordinates(operation), Visit(meta.values[0]).As(type)),
type};
}
Expression Assign(Operation operation) {
const Node& dest = operation[0];
const Node& src = operation[1];
@ -1810,7 +1760,7 @@ private:
const auto meta{std::get<MetaImage>(operation.GetMeta())};
return {fmt::format("imageLoad({}, {}){}", GetImage(meta.image),
BuildIntegerCoordinates(operation), GetSwizzle(meta.element)),
Type::Float};
Type::Uint};
}
Expression ImageStore(Operation operation) {
@ -1820,31 +1770,14 @@ private:
return {};
}
Expression AtomicImageAdd(Operation operation) {
return AtomicImage(operation, "imageAtomicAdd");
}
template <const std::string_view& opname>
Expression AtomicImage(Operation operation) {
const auto meta{std::get<MetaImage>(operation.GetMeta())};
ASSERT(meta.values.size() == 1);
Expression AtomicImageMin(Operation operation) {
return AtomicImage(operation, "imageAtomicMin");
}
Expression AtomicImageMax(Operation operation) {
return AtomicImage(operation, "imageAtomicMax");
}
Expression AtomicImageAnd(Operation operation) {
return AtomicImage(operation, "imageAtomicAnd");
}
Expression AtomicImageOr(Operation operation) {
return AtomicImage(operation, "imageAtomicOr");
}
Expression AtomicImageXor(Operation operation) {
return AtomicImage(operation, "imageAtomicXor");
}
Expression AtomicImageExchange(Operation operation) {
return AtomicImage(operation, "imageAtomicExchange");
return {fmt::format("imageAtomic{}({}, {}, {})", opname, GetImage(meta.image),
BuildIntegerCoordinates(operation), Visit(meta.values[0]).AsUint()),
Type::Uint};
}
Expression Branch(Operation operation) {
@ -2039,6 +1972,12 @@ private:
Func() = delete;
~Func() = delete;
static constexpr std::string_view Add = "Add";
static constexpr std::string_view And = "And";
static constexpr std::string_view Or = "Or";
static constexpr std::string_view Xor = "Xor";
static constexpr std::string_view Exchange = "Exchange";
static constexpr std::string_view ShuffleIndexed = "shuffleNV";
static constexpr std::string_view ShuffleUp = "shuffleUpNV";
static constexpr std::string_view ShuffleDown = "shuffleDownNV";
@ -2178,13 +2117,12 @@ private:
&GLSLDecompiler::ImageLoad,
&GLSLDecompiler::ImageStore,
&GLSLDecompiler::AtomicImageAdd,
&GLSLDecompiler::AtomicImageMin,
&GLSLDecompiler::AtomicImageMax,
&GLSLDecompiler::AtomicImageAnd,
&GLSLDecompiler::AtomicImageOr,
&GLSLDecompiler::AtomicImageXor,
&GLSLDecompiler::AtomicImageExchange,
&GLSLDecompiler::AtomicImage<Func::Add>,
&GLSLDecompiler::AtomicImage<Func::And>,
&GLSLDecompiler::AtomicImage<Func::Or>,
&GLSLDecompiler::AtomicImage<Func::Xor>,
&GLSLDecompiler::AtomicImage<Func::Exchange>,
&GLSLDecompiler::Branch,
&GLSLDecompiler::BranchIndirect,

View file

@ -343,20 +343,17 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn
u8 is_bindless{};
u8 is_written{};
u8 is_read{};
u8 is_size_known{};
u32 size{};
u8 is_atomic{};
if (!LoadObjectFromPrecompiled(offset) || !LoadObjectFromPrecompiled(index) ||
!LoadObjectFromPrecompiled(type) || !LoadObjectFromPrecompiled(is_bindless) ||
!LoadObjectFromPrecompiled(is_written) || !LoadObjectFromPrecompiled(is_read) ||
!LoadObjectFromPrecompiled(is_size_known) || !LoadObjectFromPrecompiled(size)) {
!LoadObjectFromPrecompiled(is_atomic)) {
return {};
}
entry.entries.images.emplace_back(
static_cast<std::size_t>(offset), static_cast<std::size_t>(index),
static_cast<Tegra::Shader::ImageType>(type), is_bindless != 0, is_written != 0,
is_read != 0,
is_size_known ? std::make_optional(static_cast<Tegra::Shader::ImageAtomicSize>(size))
: std::nullopt);
is_read != 0, is_atomic != 0);
}
u32 global_memory_count{};
@ -429,14 +426,13 @@ bool ShaderDiskCacheOpenGL::SaveDecompiledFile(u64 unique_identifier, const std:
return false;
}
for (const auto& image : entries.images) {
const u32 size = image.IsSizeKnown() ? static_cast<u32>(image.GetSize()) : 0U;
if (!SaveObjectToPrecompiled(static_cast<u64>(image.GetOffset())) ||
!SaveObjectToPrecompiled(static_cast<u64>(image.GetIndex())) ||
!SaveObjectToPrecompiled(static_cast<u32>(image.GetType())) ||
!SaveObjectToPrecompiled(static_cast<u8>(image.IsBindless() ? 1 : 0)) ||
!SaveObjectToPrecompiled(static_cast<u8>(image.IsWritten() ? 1 : 0)) ||
!SaveObjectToPrecompiled(static_cast<u8>(image.IsRead() ? 1 : 0)) ||
!SaveObjectToPrecompiled(image.IsSizeKnown()) || !SaveObjectToPrecompiled(size)) {
!SaveObjectToPrecompiled(static_cast<u8>(image.IsAtomic() ? 1 : 0))) {
return false;
}
}