shader_ir: Implement ST_S
This instruction writes to a memory buffer shared with threads within the same work group. It is known as "shared" memory in GLSL.
This commit is contained in:
parent
953d49810a
commit
f17415d431
|
@ -35,7 +35,7 @@ u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
||||||
const Instruction instr = {program_code[pc]};
|
const Instruction instr = {program_code[pc]};
|
||||||
|
@ -209,27 +209,34 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::ST_L: {
|
case OpCode::Id::ST_L:
|
||||||
LOG_DEBUG(HW_GPU, "ST_L cache management mode: {}",
|
LOG_DEBUG(HW_GPU, "ST_L cache management mode: {}",
|
||||||
static_cast<u64>(instr.st_l.cache_management.Value()));
|
static_cast<u64>(instr.st_l.cache_management.Value()));
|
||||||
|
[[fallthrough]];
|
||||||
const auto GetLmemAddr = [&](s32 offset) {
|
case OpCode::Id::ST_S: {
|
||||||
|
const auto GetAddress = [&](s32 offset) {
|
||||||
ASSERT(offset % 4 == 0);
|
ASSERT(offset % 4 == 0);
|
||||||
const Node immediate = Immediate(static_cast<s32>(instr.smem_imm) + offset);
|
const Node immediate = Immediate(static_cast<s32>(instr.smem_imm) + offset);
|
||||||
return Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), immediate);
|
return Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), immediate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const auto set_memory = opcode->get().GetId() == OpCode::Id::ST_L
|
||||||
|
? &ShaderIR::SetLocalMemory
|
||||||
|
: &ShaderIR::SetSharedMemory;
|
||||||
|
|
||||||
switch (instr.ldst_sl.type.Value()) {
|
switch (instr.ldst_sl.type.Value()) {
|
||||||
case Tegra::Shader::StoreType::Bits128:
|
case Tegra::Shader::StoreType::Bits128:
|
||||||
SetLocalMemory(bb, GetLmemAddr(12), GetRegister(instr.gpr0.Value() + 3));
|
(this->*set_memory)(bb, GetAddress(12), GetRegister(instr.gpr0.Value() + 3));
|
||||||
SetLocalMemory(bb, GetLmemAddr(8), GetRegister(instr.gpr0.Value() + 2));
|
(this->*set_memory)(bb, GetAddress(8), GetRegister(instr.gpr0.Value() + 2));
|
||||||
|
[[fallthrough]];
|
||||||
case Tegra::Shader::StoreType::Bits64:
|
case Tegra::Shader::StoreType::Bits64:
|
||||||
SetLocalMemory(bb, GetLmemAddr(4), GetRegister(instr.gpr0.Value() + 1));
|
(this->*set_memory)(bb, GetAddress(4), GetRegister(instr.gpr0.Value() + 1));
|
||||||
|
[[fallthrough]];
|
||||||
case Tegra::Shader::StoreType::Bits32:
|
case Tegra::Shader::StoreType::Bits32:
|
||||||
SetLocalMemory(bb, GetLmemAddr(0), GetRegister(instr.gpr0));
|
(this->*set_memory)(bb, GetAddress(0), GetRegister(instr.gpr0));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_MSG("ST_L Unhandled type: {}",
|
UNIMPLEMENTED_MSG("{} unhandled type: {}", opcode->get().GetName(),
|
||||||
static_cast<u32>(instr.ldst_sl.type.Value()));
|
static_cast<u32>(instr.ldst_sl.type.Value()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -198,12 +198,13 @@ class PredicateNode;
|
||||||
class AbufNode;
|
class AbufNode;
|
||||||
class CbufNode;
|
class CbufNode;
|
||||||
class LmemNode;
|
class LmemNode;
|
||||||
|
class SmemNode;
|
||||||
class GmemNode;
|
class GmemNode;
|
||||||
class CommentNode;
|
class CommentNode;
|
||||||
|
|
||||||
using NodeData =
|
using NodeData =
|
||||||
std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode,
|
std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode,
|
||||||
PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>;
|
PredicateNode, AbufNode, CbufNode, LmemNode, SmemNode, GmemNode, CommentNode>;
|
||||||
using Node = std::shared_ptr<NodeData>;
|
using Node = std::shared_ptr<NodeData>;
|
||||||
using Node4 = std::array<Node, 4>;
|
using Node4 = std::array<Node, 4>;
|
||||||
using NodeBlock = std::vector<Node>;
|
using NodeBlock = std::vector<Node>;
|
||||||
|
@ -536,6 +537,19 @@ private:
|
||||||
Node address;
|
Node address;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Shared memory node
|
||||||
|
class SmemNode final {
|
||||||
|
public:
|
||||||
|
explicit SmemNode(Node address) : address{std::move(address)} {}
|
||||||
|
|
||||||
|
const Node& GetAddress() const {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Node address;
|
||||||
|
};
|
||||||
|
|
||||||
/// Global memory node
|
/// Global memory node
|
||||||
class GmemNode final {
|
class GmemNode final {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -137,6 +137,10 @@ Node ShaderIR::GetLocalMemory(Node address) {
|
||||||
return MakeNode<LmemNode>(std::move(address));
|
return MakeNode<LmemNode>(std::move(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node ShaderIR::GetSharedMemory(Node address) {
|
||||||
|
return MakeNode<SmemNode>(std::move(address));
|
||||||
|
}
|
||||||
|
|
||||||
Node ShaderIR::GetTemporary(u32 id) {
|
Node ShaderIR::GetTemporary(u32 id) {
|
||||||
return GetRegister(Register::ZeroIndex + 1 + id);
|
return GetRegister(Register::ZeroIndex + 1 + id);
|
||||||
}
|
}
|
||||||
|
@ -378,6 +382,11 @@ void ShaderIR::SetLocalMemory(NodeBlock& bb, Node address, Node value) {
|
||||||
Operation(OperationCode::Assign, GetLocalMemory(std::move(address)), std::move(value)));
|
Operation(OperationCode::Assign, GetLocalMemory(std::move(address)), std::move(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderIR::SetSharedMemory(NodeBlock& bb, Node address, Node value) {
|
||||||
|
bb.push_back(
|
||||||
|
Operation(OperationCode::Assign, GetSharedMemory(std::move(address)), std::move(value)));
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderIR::SetTemporary(NodeBlock& bb, u32 id, Node value) {
|
void ShaderIR::SetTemporary(NodeBlock& bb, u32 id, Node value) {
|
||||||
SetRegister(bb, Register::ZeroIndex + 1 + id, std::move(value));
|
SetRegister(bb, Register::ZeroIndex + 1 + id, std::move(value));
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,6 +208,8 @@ private:
|
||||||
Node GetInternalFlag(InternalFlag flag, bool negated = false);
|
Node GetInternalFlag(InternalFlag flag, bool negated = false);
|
||||||
/// Generates a node representing a local memory address
|
/// Generates a node representing a local memory address
|
||||||
Node GetLocalMemory(Node address);
|
Node GetLocalMemory(Node address);
|
||||||
|
/// Generates a node representing a shared memory address
|
||||||
|
Node GetSharedMemory(Node address);
|
||||||
/// Generates a temporary, internally it uses a post-RZ register
|
/// Generates a temporary, internally it uses a post-RZ register
|
||||||
Node GetTemporary(u32 id);
|
Node GetTemporary(u32 id);
|
||||||
|
|
||||||
|
@ -217,8 +219,10 @@ private:
|
||||||
void SetPredicate(NodeBlock& bb, u64 dest, Node src);
|
void SetPredicate(NodeBlock& bb, u64 dest, Node src);
|
||||||
/// Sets an internal flag. src value must be a bool-evaluated node
|
/// Sets an internal flag. src value must be a bool-evaluated node
|
||||||
void SetInternalFlag(NodeBlock& bb, InternalFlag flag, Node value);
|
void SetInternalFlag(NodeBlock& bb, InternalFlag flag, Node value);
|
||||||
/// Sets a local memory address. address and value must be a number-evaluated node
|
/// Sets a local memory address with a value.
|
||||||
void SetLocalMemory(NodeBlock& bb, Node address, Node value);
|
void SetLocalMemory(NodeBlock& bb, Node address, Node value);
|
||||||
|
/// Sets a shared memory address with a value.
|
||||||
|
void SetSharedMemory(NodeBlock& bb, Node address, Node value);
|
||||||
/// Sets a temporary. Internally it uses a post-RZ register
|
/// Sets a temporary. Internally it uses a post-RZ register
|
||||||
void SetTemporary(NodeBlock& bb, u32 id, Node value);
|
void SetTemporary(NodeBlock& bb, u32 id, Node value);
|
||||||
|
|
||||||
|
|
Reference in New Issue