summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorGravatar bunnei2019-09-14 00:45:51 -0400
committerGravatar GitHub2019-09-14 00:45:51 -0400
commit3cc27e4ddaf6a8c7449b2c2b7c8d9aa7fbf248ad (patch)
tree3e6e0e818e952a038fbe10262bf39cf6d52eaa61 /src/video_core/renderer_opengl
parentMerge pull request #2823 from ReinUsesLisp/shr-clamp (diff)
parentshader/image: Implement SUATOM and fix SUST (diff)
downloadyuzu-3cc27e4ddaf6a8c7449b2c2b7c8d9aa7fbf248ad.tar.gz
yuzu-3cc27e4ddaf6a8c7449b2c2b7c8d9aa7fbf248ad.tar.xz
yuzu-3cc27e4ddaf6a8c7449b2c2b7c8d9aa7fbf248ad.zip
Merge pull request #2757 from ReinUsesLisp/suatom
shader/image: Implement SUATOM and fix SUST
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp145
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.cpp20
2 files changed, 133 insertions, 32 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 6edb2ca38..137b23740 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -706,7 +706,7 @@ private:
706 void DeclareImages() { 706 void DeclareImages() {
707 const auto& images{ir.GetImages()}; 707 const auto& images{ir.GetImages()};
708 for (const auto& [offset, image] : images) { 708 for (const auto& [offset, image] : images) {
709 const std::string image_type = [&]() { 709 const char* image_type = [&] {
710 switch (image.GetType()) { 710 switch (image.GetType()) {
711 case Tegra::Shader::ImageType::Texture1D: 711 case Tegra::Shader::ImageType::Texture1D:
712 return "image1D"; 712 return "image1D";
@@ -725,6 +725,23 @@ private:
725 return "image1D"; 725 return "image1D";
726 } 726 }
727 }(); 727 }();
728
729 const auto [type_prefix, format] = [&]() -> std::pair<const char*, const char*> {
730 if (!image.IsSizeKnown()) {
731 return {"", ""};
732 }
733 switch (image.GetSize()) {
734 case Tegra::Shader::ImageAtomicSize::U32:
735 return {"u", "r32ui, "};
736 case Tegra::Shader::ImageAtomicSize::S32:
737 return {"i", "r32i, "};
738 default:
739 UNIMPLEMENTED_MSG("Unimplemented atomic size={}",
740 static_cast<u32>(image.GetSize()));
741 return {"", ""};
742 }
743 }();
744
728 std::string qualifier = "coherent volatile"; 745 std::string qualifier = "coherent volatile";
729 if (image.IsRead() && !image.IsWritten()) { 746 if (image.IsRead() && !image.IsWritten()) {
730 qualifier += " readonly"; 747 qualifier += " readonly";
@@ -1180,6 +1197,74 @@ private:
1180 return expr; 1197 return expr;
1181 } 1198 }
1182 1199
1200 std::string BuildIntegerCoordinates(Operation operation) {
1201 constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
1202 const std::size_t coords_count{operation.GetOperandsCount()};
1203 std::string expr = constructors.at(coords_count - 1);
1204 for (std::size_t i = 0; i < coords_count; ++i) {
1205 expr += VisitOperand(operation, i).AsInt();
1206 if (i + 1 < coords_count) {
1207 expr += ", ";
1208 }
1209 }
1210 expr += ')';
1211 return expr;
1212 }
1213
1214 std::string BuildImageValues(Operation operation) {
1215 const auto meta{std::get<MetaImage>(operation.GetMeta())};
1216 const auto [constructors, type] = [&]() -> std::pair<std::array<const char*, 4>, Type> {
1217 constexpr std::array float_constructors{"float", "vec2", "vec3", "vec4"};
1218 if (!meta.image.IsSizeKnown()) {
1219 return {float_constructors, Type::Float};
1220 }
1221 switch (meta.image.GetSize()) {
1222 case Tegra::Shader::ImageAtomicSize::U32:
1223 return {{"uint", "uvec2", "uvec3", "uvec4"}, Type::Uint};
1224 case Tegra::Shader::ImageAtomicSize::S32:
1225 return {{"int", "ivec2", "ivec3", "ivec4"}, Type::Uint};
1226 default:
1227 UNIMPLEMENTED_MSG("Unimplemented image size={}",
1228 static_cast<u32>(meta.image.GetSize()));
1229 return {float_constructors, Type::Float};
1230 }
1231 }();
1232
1233 const std::size_t values_count{meta.values.size()};
1234 std::string expr = fmt::format("{}(", constructors.at(values_count - 1));
1235 for (std::size_t i = 0; i < values_count; ++i) {
1236 expr += Visit(meta.values.at(i)).As(type);
1237 if (i + 1 < values_count) {
1238 expr += ", ";
1239 }
1240 }
1241 expr += ')';
1242 return expr;
1243 }
1244
1245 Expression AtomicImage(Operation operation, const char* opname) {
1246 constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
1247 const auto meta{std::get<MetaImage>(operation.GetMeta())};
1248 ASSERT(meta.values.size() == 1);
1249 ASSERT(meta.image.IsSizeKnown());
1250
1251 const auto type = [&]() {
1252 switch (const auto size = meta.image.GetSize()) {
1253 case Tegra::Shader::ImageAtomicSize::U32:
1254 return Type::Uint;
1255 case Tegra::Shader::ImageAtomicSize::S32:
1256 return Type::Int;
1257 default:
1258 UNIMPLEMENTED_MSG("Unimplemented image size={}", static_cast<u32>(size));
1259 return Type::Uint;
1260 }
1261 }();
1262
1263 return {fmt::format("{}({}, {}, {})", opname, GetImage(meta.image),
1264 BuildIntegerCoordinates(operation), Visit(meta.values[0]).As(type)),
1265 type};
1266 }
1267
1183 Expression Assign(Operation operation) { 1268 Expression Assign(Operation operation) {
1184 const Node& dest = operation[0]; 1269 const Node& dest = operation[0];
1185 const Node& src = operation[1]; 1270 const Node& src = operation[1];
@@ -1694,36 +1779,37 @@ private:
1694 } 1779 }
1695 1780
1696 Expression ImageStore(Operation operation) { 1781 Expression ImageStore(Operation operation) {
1697 constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
1698 const auto meta{std::get<MetaImage>(operation.GetMeta())}; 1782 const auto meta{std::get<MetaImage>(operation.GetMeta())};
1783 code.AddLine("imageStore({}, {}, {});", GetImage(meta.image),
1784 BuildIntegerCoordinates(operation), BuildImageValues(operation));
1785 return {};
1786 }
1699 1787
1700 std::string expr = "imageStore("; 1788 Expression AtomicImageAdd(Operation operation) {
1701 expr += GetImage(meta.image); 1789 return AtomicImage(operation, "imageAtomicAdd");
1702 expr += ", "; 1790 }
1703 1791
1704 const std::size_t coords_count{operation.GetOperandsCount()}; 1792 Expression AtomicImageMin(Operation operation) {
1705 expr += constructors.at(coords_count - 1); 1793 return AtomicImage(operation, "imageAtomicMin");
1706 for (std::size_t i = 0; i < coords_count; ++i) { 1794 }
1707 expr += VisitOperand(operation, i).AsInt();
1708 if (i + 1 < coords_count) {
1709 expr += ", ";
1710 }
1711 }
1712 expr += "), ";
1713 1795
1714 const std::size_t values_count{meta.values.size()}; 1796 Expression AtomicImageMax(Operation operation) {
1715 UNIMPLEMENTED_IF(values_count != 4); 1797 return AtomicImage(operation, "imageAtomicMax");
1716 expr += "vec4("; 1798 }
1717 for (std::size_t i = 0; i < values_count; ++i) { 1799 Expression AtomicImageAnd(Operation operation) {
1718 expr += Visit(meta.values.at(i)).AsFloat(); 1800 return AtomicImage(operation, "imageAtomicAnd");
1719 if (i + 1 < values_count) { 1801 }
1720 expr += ", ";
1721 }
1722 }
1723 expr += "));";
1724 1802
1725 code.AddLine(expr); 1803 Expression AtomicImageOr(Operation operation) {
1726 return {}; 1804 return AtomicImage(operation, "imageAtomicOr");
1805 }
1806
1807 Expression AtomicImageXor(Operation operation) {
1808 return AtomicImage(operation, "imageAtomicXor");
1809 }
1810
1811 Expression AtomicImageExchange(Operation operation) {
1812 return AtomicImage(operation, "imageAtomicExchange");
1727 } 1813 }
1728 1814
1729 Expression Branch(Operation operation) { 1815 Expression Branch(Operation operation) {
@@ -2019,6 +2105,13 @@ private:
2019 &GLSLDecompiler::TexelFetch, 2105 &GLSLDecompiler::TexelFetch,
2020 2106
2021 &GLSLDecompiler::ImageStore, 2107 &GLSLDecompiler::ImageStore,
2108 &GLSLDecompiler::AtomicImageAdd,
2109 &GLSLDecompiler::AtomicImageMin,
2110 &GLSLDecompiler::AtomicImageMax,
2111 &GLSLDecompiler::AtomicImageAnd,
2112 &GLSLDecompiler::AtomicImageOr,
2113 &GLSLDecompiler::AtomicImageXor,
2114 &GLSLDecompiler::AtomicImageExchange,
2022 2115
2023 &GLSLDecompiler::Branch, 2116 &GLSLDecompiler::Branch,
2024 &GLSLDecompiler::BranchIndirect, 2117 &GLSLDecompiler::BranchIndirect,
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
index 5450feedf..f141c4e3b 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
@@ -341,16 +341,22 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn
341 u64 index{}; 341 u64 index{};
342 u32 type{}; 342 u32 type{};
343 u8 is_bindless{}; 343 u8 is_bindless{};
344 u8 is_read{};
345 u8 is_written{}; 344 u8 is_written{};
345 u8 is_read{};
346 u8 is_size_known{};
347 u32 size{};
346 if (!LoadObjectFromPrecompiled(offset) || !LoadObjectFromPrecompiled(index) || 348 if (!LoadObjectFromPrecompiled(offset) || !LoadObjectFromPrecompiled(index) ||
347 !LoadObjectFromPrecompiled(type) || !LoadObjectFromPrecompiled(is_bindless) || 349 !LoadObjectFromPrecompiled(type) || !LoadObjectFromPrecompiled(is_bindless) ||
348 !LoadObjectFromPrecompiled(is_read) || !LoadObjectFromPrecompiled(is_written)) { 350 !LoadObjectFromPrecompiled(is_written) || !LoadObjectFromPrecompiled(is_read) ||
351 !LoadObjectFromPrecompiled(is_size_known) || !LoadObjectFromPrecompiled(size)) {
349 return {}; 352 return {};
350 } 353 }
351 entry.entries.images.emplace_back(static_cast<u64>(offset), static_cast<std::size_t>(index), 354 entry.entries.images.emplace_back(
352 static_cast<Tegra::Shader::ImageType>(type), 355 static_cast<std::size_t>(offset), static_cast<std::size_t>(index),
353 is_bindless != 0, is_written != 0, is_read != 0); 356 static_cast<Tegra::Shader::ImageType>(type), is_bindless != 0, is_written != 0,
357 is_read != 0,
358 is_size_known ? std::make_optional(static_cast<Tegra::Shader::ImageAtomicSize>(size))
359 : std::nullopt);
354 } 360 }
355 361
356 u32 global_memory_count{}; 362 u32 global_memory_count{};
@@ -429,12 +435,14 @@ bool ShaderDiskCacheOpenGL::SaveDecompiledFile(u64 unique_identifier, const std:
429 return false; 435 return false;
430 } 436 }
431 for (const auto& image : entries.images) { 437 for (const auto& image : entries.images) {
438 const u32 size = image.IsSizeKnown() ? static_cast<u32>(image.GetSize()) : 0U;
432 if (!SaveObjectToPrecompiled(static_cast<u64>(image.GetOffset())) || 439 if (!SaveObjectToPrecompiled(static_cast<u64>(image.GetOffset())) ||
433 !SaveObjectToPrecompiled(static_cast<u64>(image.GetIndex())) || 440 !SaveObjectToPrecompiled(static_cast<u64>(image.GetIndex())) ||
434 !SaveObjectToPrecompiled(static_cast<u32>(image.GetType())) || 441 !SaveObjectToPrecompiled(static_cast<u32>(image.GetType())) ||
435 !SaveObjectToPrecompiled(static_cast<u8>(image.IsBindless() ? 1 : 0)) || 442 !SaveObjectToPrecompiled(static_cast<u8>(image.IsBindless() ? 1 : 0)) ||
443 !SaveObjectToPrecompiled(static_cast<u8>(image.IsWritten() ? 1 : 0)) ||
436 !SaveObjectToPrecompiled(static_cast<u8>(image.IsRead() ? 1 : 0)) || 444 !SaveObjectToPrecompiled(static_cast<u8>(image.IsRead() ? 1 : 0)) ||
437 !SaveObjectToPrecompiled(static_cast<u8>(image.IsWritten() ? 1 : 0))) { 445 !SaveObjectToPrecompiled(image.IsSizeKnown()) || !SaveObjectToPrecompiled(size)) {
438 return false; 446 return false;
439 } 447 }
440 } 448 }