summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl/gl_shader_decompiler.cpp')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp44
1 files changed, 43 insertions, 1 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index b87ee2ae8..49f0b1620 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -44,8 +44,9 @@ using Operation = const OperationNode&;
enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat };
struct TextureAoffi {};
+struct TextureDerivates {};
using TextureArgument = std::pair<Type, Node>;
-using TextureIR = std::variant<TextureAoffi, TextureArgument>;
+using TextureIR = std::variant<TextureAoffi, TextureDerivates, TextureArgument>;
constexpr u32 MAX_CONSTBUFFER_ELEMENTS =
static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float));
@@ -1129,6 +1130,8 @@ private:
expr += GenerateTextureArgument(*argument);
} else if (std::holds_alternative<TextureAoffi>(variant)) {
expr += GenerateTextureAoffi(meta->aoffi);
+ } else if (std::holds_alternative<TextureDerivates>(variant)) {
+ expr += GenerateTextureDerivates(meta->derivates);
} else {
UNREACHABLE();
}
@@ -1198,6 +1201,36 @@ private:
return expr;
}
+ std::string GenerateTextureDerivates(const std::vector<Node>& derivates) {
+ if (derivates.empty()) {
+ return {};
+ }
+ constexpr std::array coord_constructors = {"float", "vec2", "vec3"};
+ std::string expr = ", ";
+ const std::size_t components = derivates.size() / 2;
+ std::string dx = coord_constructors.at(components - 1);
+ std::string dy = coord_constructors.at(components - 1);
+ dx += '(';
+ dy += '(';
+
+ for (std::size_t index = 0; index < components; ++index) {
+ const auto operand_x{derivates.at(index * 2)};
+ const auto operand_y{derivates.at(index * 2 + 1)};
+ dx += Visit(operand_x).AsFloat();
+ dy += Visit(operand_y).AsFloat();
+
+ if (index + 1 < components) {
+ dx += ", ";
+ dy += ", ";
+ }
+ }
+ dx += ')';
+ dy += ')';
+ expr += dx + ", " + dy;
+
+ return expr;
+ }
+
std::string BuildIntegerCoordinates(Operation operation) {
constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
const std::size_t coords_count{operation.GetOperandsCount()};
@@ -1777,6 +1810,14 @@ private:
return {tmp, Type::Float};
}
+ Expression TextureGradient(Operation operation) {
+ const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
+ ASSERT(meta);
+
+ std::string expr = GenerateTexture(operation, "Grad", {TextureDerivates{}, TextureAoffi{}});
+ return {expr + GetSwizzle(meta->element), Type::Float};
+ }
+
Expression ImageLoad(Operation operation) {
if (!device.HasImageLoadFormatted()) {
LOG_ERROR(Render_OpenGL,
@@ -2131,6 +2172,7 @@ private:
&GLSLDecompiler::TextureQueryDimensions,
&GLSLDecompiler::TextureQueryLod,
&GLSLDecompiler::TexelFetch,
+ &GLSLDecompiler::TextureGradient,
&GLSLDecompiler::ImageLoad,
&GLSLDecompiler::ImageStore,