diff options
| author | 2019-09-14 00:45:51 -0400 | |
|---|---|---|
| committer | 2019-09-14 00:45:51 -0400 | |
| commit | 3cc27e4ddaf6a8c7449b2c2b7c8d9aa7fbf248ad (patch) | |
| tree | 3e6e0e818e952a038fbe10262bf39cf6d52eaa61 /src/video_core/renderer_opengl | |
| parent | Merge pull request #2823 from ReinUsesLisp/shr-clamp (diff) | |
| parent | shader/image: Implement SUATOM and fix SUST (diff) | |
| download | yuzu-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.cpp | 145 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | 20 |
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 | } |