Shader_IR: Implement TXD instruction.
This commit is contained in:
parent
f3d1b370aa
commit
cd0f5dfc17
5 changed files with 120 additions and 8 deletions
|
@ -1445,6 +1445,26 @@ union Instruction {
|
||||||
}
|
}
|
||||||
} tlds;
|
} tlds;
|
||||||
|
|
||||||
|
union {
|
||||||
|
BitField<28, 1, u64> is_array;
|
||||||
|
BitField<29, 2, TextureType> texture_type;
|
||||||
|
BitField<35, 1, u64> aoffi_flag;
|
||||||
|
BitField<49, 1, u64> nodep_flag;
|
||||||
|
|
||||||
|
bool UsesMiscMode(TextureMiscMode mode) const {
|
||||||
|
switch (mode) {
|
||||||
|
case TextureMiscMode::AOFFI:
|
||||||
|
return aoffi_flag != 0;
|
||||||
|
case TextureMiscMode::NODEP:
|
||||||
|
return nodep_flag != 0;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} txd;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField<24, 2, StoreCacheManagement> cache_management;
|
BitField<24, 2, StoreCacheManagement> cache_management;
|
||||||
BitField<33, 3, ImageType> image_type;
|
BitField<33, 3, ImageType> image_type;
|
||||||
|
|
|
@ -44,8 +44,9 @@ using Operation = const OperationNode&;
|
||||||
enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat };
|
enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat };
|
||||||
|
|
||||||
struct TextureAoffi {};
|
struct TextureAoffi {};
|
||||||
|
struct TextureDerivates {};
|
||||||
using TextureArgument = std::pair<Type, Node>;
|
using TextureArgument = std::pair<Type, Node>;
|
||||||
using TextureIR = std::variant<TextureAoffi, TextureArgument>;
|
using TextureIR = std::variant<TextureAoffi, TextureDerivates, TextureArgument>;
|
||||||
|
|
||||||
constexpr u32 MAX_CONSTBUFFER_ELEMENTS =
|
constexpr u32 MAX_CONSTBUFFER_ELEMENTS =
|
||||||
static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float));
|
static_cast<u32>(Maxwell::MaxConstBufferSize) / (4 * sizeof(float));
|
||||||
|
@ -1129,6 +1130,8 @@ private:
|
||||||
expr += GenerateTextureArgument(*argument);
|
expr += GenerateTextureArgument(*argument);
|
||||||
} else if (std::holds_alternative<TextureAoffi>(variant)) {
|
} else if (std::holds_alternative<TextureAoffi>(variant)) {
|
||||||
expr += GenerateTextureAoffi(meta->aoffi);
|
expr += GenerateTextureAoffi(meta->aoffi);
|
||||||
|
} else if (std::holds_alternative<TextureDerivates>(variant)) {
|
||||||
|
expr += GenerateTextureDerivates(meta->derivates);
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -1198,6 +1201,36 @@ private:
|
||||||
return expr;
|
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) {
|
std::string BuildIntegerCoordinates(Operation operation) {
|
||||||
constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
|
constexpr std::array constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
|
||||||
const std::size_t coords_count{operation.GetOperandsCount()};
|
const std::size_t coords_count{operation.GetOperandsCount()};
|
||||||
|
@ -1777,6 +1810,14 @@ private:
|
||||||
return {tmp, Type::Float};
|
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) {
|
Expression ImageLoad(Operation operation) {
|
||||||
if (!device.HasImageLoadFormatted()) {
|
if (!device.HasImageLoadFormatted()) {
|
||||||
LOG_ERROR(Render_OpenGL,
|
LOG_ERROR(Render_OpenGL,
|
||||||
|
@ -2131,6 +2172,7 @@ private:
|
||||||
&GLSLDecompiler::TextureQueryDimensions,
|
&GLSLDecompiler::TextureQueryDimensions,
|
||||||
&GLSLDecompiler::TextureQueryLod,
|
&GLSLDecompiler::TextureQueryLod,
|
||||||
&GLSLDecompiler::TexelFetch,
|
&GLSLDecompiler::TexelFetch,
|
||||||
|
&GLSLDecompiler::TextureGradient,
|
||||||
|
|
||||||
&GLSLDecompiler::ImageLoad,
|
&GLSLDecompiler::ImageLoad,
|
||||||
&GLSLDecompiler::ImageStore,
|
&GLSLDecompiler::ImageStore,
|
||||||
|
|
|
@ -982,6 +982,11 @@ private:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id TextureGradient(Operation operation) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Id ImageLoad(Operation operation) {
|
Id ImageLoad(Operation operation) {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
return {};
|
return {};
|
||||||
|
@ -1474,6 +1479,7 @@ private:
|
||||||
&SPIRVDecompiler::TextureQueryDimensions,
|
&SPIRVDecompiler::TextureQueryDimensions,
|
||||||
&SPIRVDecompiler::TextureQueryLod,
|
&SPIRVDecompiler::TextureQueryLod,
|
||||||
&SPIRVDecompiler::TexelFetch,
|
&SPIRVDecompiler::TexelFetch,
|
||||||
|
&SPIRVDecompiler::TextureGradient,
|
||||||
|
|
||||||
&SPIRVDecompiler::ImageLoad,
|
&SPIRVDecompiler::ImageLoad,
|
||||||
&SPIRVDecompiler::ImageStore,
|
&SPIRVDecompiler::ImageStore,
|
||||||
|
|
|
@ -134,13 +134,55 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
|
||||||
Node4 values;
|
Node4 values;
|
||||||
for (u32 element = 0; element < values.size(); ++element) {
|
for (u32 element = 0; element < values.size(); ++element) {
|
||||||
auto coords_copy = coords;
|
auto coords_copy = coords;
|
||||||
MetaTexture meta{sampler, {}, {}, {}, {}, {}, component, element};
|
MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, component, element};
|
||||||
values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
|
values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteTexsInstructionFloat(bb, instr, values, true);
|
WriteTexsInstructionFloat(bb, instr, values, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OpCode::Id::TXD_B:
|
||||||
|
is_bindless = true;
|
||||||
|
[[fallthrough]];
|
||||||
|
case OpCode::Id::TXD: {
|
||||||
|
UNIMPLEMENTED_IF_MSG(instr.txd.UsesMiscMode(TextureMiscMode::AOFFI),
|
||||||
|
"AOFFI is not implemented");
|
||||||
|
const auto is_array = static_cast<bool>(instr.txd.is_array != 0);
|
||||||
|
UNIMPLEMENTED_IF_MSG(is_array, "TXD Array is not implemented");
|
||||||
|
|
||||||
|
u64 base_reg = instr.gpr8.Value();
|
||||||
|
const auto derivate_reg = instr.gpr20.Value();
|
||||||
|
const auto texture_type = instr.txd.texture_type.Value();
|
||||||
|
const auto coord_count = GetCoordCount(texture_type);
|
||||||
|
|
||||||
|
const auto& sampler = is_bindless
|
||||||
|
? GetBindlessSampler(base_reg, {{texture_type, false, false}})
|
||||||
|
: GetSampler(instr.sampler, {{texture_type, false, false}});
|
||||||
|
if (is_bindless) {
|
||||||
|
base_reg++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Node> coords;
|
||||||
|
std::vector<Node> derivates;
|
||||||
|
for (std::size_t i = 0; i < coord_count; ++i) {
|
||||||
|
coords.push_back(GetRegister(base_reg + i));
|
||||||
|
const std::size_t derivate = i * 2;
|
||||||
|
derivates.push_back(GetRegister(derivate_reg + derivate));
|
||||||
|
derivates.push_back(GetRegister(derivate_reg + derivate + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node4 values;
|
||||||
|
for (u32 element = 0; element < values.size(); ++element) {
|
||||||
|
auto coords_copy = coords;
|
||||||
|
MetaTexture meta{sampler, {}, {}, {}, derivates, {}, {}, {}, element};
|
||||||
|
values[element] =
|
||||||
|
Operation(OperationCode::TextureGradient, meta, std::move(coords_copy));
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteTexInstructionFloat(bb, instr, values);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OpCode::Id::TXQ_B:
|
case OpCode::Id::TXQ_B:
|
||||||
is_bindless = true;
|
is_bindless = true;
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
@ -158,7 +200,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
|
||||||
if (!instr.txq.IsComponentEnabled(element)) {
|
if (!instr.txq.IsComponentEnabled(element)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, element};
|
MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element};
|
||||||
const Node value =
|
const Node value =
|
||||||
Operation(OperationCode::TextureQueryDimensions, meta,
|
Operation(OperationCode::TextureQueryDimensions, meta,
|
||||||
GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0)));
|
GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0)));
|
||||||
|
@ -213,7 +255,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto params = coords;
|
auto params = coords;
|
||||||
MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, element};
|
MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element};
|
||||||
const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params));
|
const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params));
|
||||||
SetTemporary(bb, indexer++, value);
|
SetTemporary(bb, indexer++, value);
|
||||||
}
|
}
|
||||||
|
@ -461,7 +503,7 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
|
||||||
Node4 values;
|
Node4 values;
|
||||||
for (u32 element = 0; element < values.size(); ++element) {
|
for (u32 element = 0; element < values.size(); ++element) {
|
||||||
auto copy_coords = coords;
|
auto copy_coords = coords;
|
||||||
MetaTexture meta{sampler, array, depth_compare, aoffi, bias, lod, {}, element};
|
MetaTexture meta{sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element};
|
||||||
values[element] = Operation(read_method, meta, std::move(copy_coords));
|
values[element] = Operation(read_method, meta, std::move(copy_coords));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,7 +636,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
|
||||||
Node4 values;
|
Node4 values;
|
||||||
for (u32 element = 0; element < values.size(); ++element) {
|
for (u32 element = 0; element < values.size(); ++element) {
|
||||||
auto coords_copy = coords;
|
auto coords_copy = coords;
|
||||||
MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, component,
|
MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component,
|
||||||
element};
|
element};
|
||||||
values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
|
values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
|
||||||
}
|
}
|
||||||
|
@ -628,7 +670,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
|
||||||
Node4 values;
|
Node4 values;
|
||||||
for (u32 element = 0; element < values.size(); ++element) {
|
for (u32 element = 0; element < values.size(); ++element) {
|
||||||
auto coords_copy = coords;
|
auto coords_copy = coords;
|
||||||
MetaTexture meta{sampler, array_register, {}, {}, {}, lod, {}, element};
|
MetaTexture meta{sampler, array_register, {}, {}, {}, {}, lod, {}, element};
|
||||||
values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
|
values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +706,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
|
||||||
Node4 values;
|
Node4 values;
|
||||||
for (u32 element = 0; element < values.size(); ++element) {
|
for (u32 element = 0; element < values.size(); ++element) {
|
||||||
auto coords_copy = coords;
|
auto coords_copy = coords;
|
||||||
MetaTexture meta{sampler, array, {}, {}, {}, lod, {}, element};
|
MetaTexture meta{sampler, array, {}, {}, {}, {}, lod, {}, element};
|
||||||
values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
|
values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
|
||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
|
|
|
@ -151,6 +151,7 @@ enum class OperationCode {
|
||||||
TextureQueryDimensions, /// (MetaTexture, float a) -> float4
|
TextureQueryDimensions, /// (MetaTexture, float a) -> float4
|
||||||
TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4
|
TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4
|
||||||
TexelFetch, /// (MetaTexture, int[N], int) -> float4
|
TexelFetch, /// (MetaTexture, int[N], int) -> float4
|
||||||
|
TextureGradient, /// (MetaTexture, float[N] coords, float[N*2] derivates) -> float4
|
||||||
|
|
||||||
ImageLoad, /// (MetaImage, int[N] coords) -> void
|
ImageLoad, /// (MetaImage, int[N] coords) -> void
|
||||||
ImageStore, /// (MetaImage, int[N] coords) -> void
|
ImageStore, /// (MetaImage, int[N] coords) -> void
|
||||||
|
@ -363,6 +364,7 @@ struct MetaTexture {
|
||||||
Node array;
|
Node array;
|
||||||
Node depth_compare;
|
Node depth_compare;
|
||||||
std::vector<Node> aoffi;
|
std::vector<Node> aoffi;
|
||||||
|
std::vector<Node> derivates;
|
||||||
Node bias;
|
Node bias;
|
||||||
Node lod;
|
Node lod;
|
||||||
Node component{};
|
Node component{};
|
||||||
|
|
Loading…
Reference in a new issue