mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
shaders: use flat exec test
This commit is contained in:
parent
13b760a539
commit
b53d59aa1f
|
|
@ -33,6 +33,7 @@ struct Context : ir::Context {
|
|||
void setConstantName(ir::Value constant);
|
||||
|
||||
ir::Value getOrCreateConstant(ir::Value typeValue, const ir::Operand &value);
|
||||
ir::Value getNull(ir::Value typeValue);
|
||||
|
||||
ir::Value getType(ir::spv::Op baseType, int width, bool isSigned);
|
||||
ir::Value getType(const TypeInfo &info);
|
||||
|
|
|
|||
|
|
@ -321,15 +321,19 @@ void spv::Context::setConstantName(ir::Value constant) {
|
|||
}
|
||||
|
||||
ir::Value spv::Context::getOrCreateConstant(ir::Value typeValue,
|
||||
const ir::Operand &value) {
|
||||
const ir::Operand &value) {
|
||||
if (typeValue == getTypeBool()) {
|
||||
return *value.getAsBool() ? getTrue() : getFalse();
|
||||
}
|
||||
return getOrCreateGlobal(ir::spv::OpConstant, {{typeValue, value}});
|
||||
}
|
||||
|
||||
ir::Value spv::Context::getNull(ir::Value typeValue) {
|
||||
return getOrCreateGlobal(ir::spv::OpConstantNull, {{typeValue}});
|
||||
}
|
||||
|
||||
ir::Value spv::Context::getType(ir::spv::Op baseType, int width,
|
||||
bool isSigned) {
|
||||
bool isSigned) {
|
||||
switch (baseType) {
|
||||
case ir::spv::OpTypeInt:
|
||||
return getTypeInt(width, isSigned);
|
||||
|
|
@ -377,7 +381,7 @@ void spv::Context::setTypeName(ir::Value type) {
|
|||
|
||||
ir::Value
|
||||
spv::Context::findGlobal(ir::spv::Op op,
|
||||
std::span<const ir::Operand> operands) const {
|
||||
std::span<const ir::Operand> operands) const {
|
||||
auto it = globals.find(ir::getInstructionId(ir::Kind::Spv, op));
|
||||
|
||||
if (it == globals.end()) {
|
||||
|
|
@ -407,9 +411,8 @@ spv::Context::findGlobal(ir::spv::Op op,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
ir::Value
|
||||
spv::Context::createGlobal(ir::spv::Op op,
|
||||
std::span<const ir::Operand> operands) {
|
||||
ir::Value spv::Context::createGlobal(ir::spv::Op op,
|
||||
std::span<const ir::Operand> operands) {
|
||||
auto builder = Builder::createAppend(*this, layout.getOrCreateGlobals(*this));
|
||||
auto result =
|
||||
builder.createValue(getUnknownLocation(), ir::Kind::Spv, op, operands);
|
||||
|
|
@ -423,8 +426,9 @@ spv::Context::createGlobal(ir::spv::Op op,
|
|||
return result;
|
||||
}
|
||||
|
||||
ir::Value spv::Context::getOrCreateGlobal(
|
||||
ir::spv::Op op, std::span<const ir::Operand> operands) {
|
||||
ir::Value
|
||||
spv::Context::getOrCreateGlobal(ir::spv::Op op,
|
||||
std::span<const ir::Operand> operands) {
|
||||
if (auto result = findGlobal(op, operands)) {
|
||||
return result;
|
||||
}
|
||||
|
|
@ -432,8 +436,7 @@ ir::Value spv::Context::getOrCreateGlobal(
|
|||
return createGlobal(op, operands);
|
||||
}
|
||||
|
||||
ir::Value spv::Context::getOperandValue(const ir::Operand &op,
|
||||
ir::Value type) {
|
||||
ir::Value spv::Context::getOperandValue(const ir::Operand &op, ir::Value type) {
|
||||
if (auto result = op.getAsValue()) {
|
||||
return result;
|
||||
}
|
||||
|
|
@ -504,9 +507,8 @@ void spv::Context::createPerVertex() {
|
|||
ir::spv::StorageClass::Output);
|
||||
}
|
||||
|
||||
ir::Value spv::Context::createUniformBuffer(int descriptorSet,
|
||||
int binding,
|
||||
ir::Value structType) {
|
||||
ir::Value spv::Context::createUniformBuffer(int descriptorSet, int binding,
|
||||
ir::Value structType) {
|
||||
auto globals = Builder::createAppend(*this, layout.getOrCreateGlobals(*this));
|
||||
auto annotations =
|
||||
Builder::createAppend(*this, layout.getOrCreateAnnotations(*this));
|
||||
|
|
@ -526,8 +528,9 @@ ir::Value spv::Context::createUniformBuffer(int descriptorSet,
|
|||
return blockVariable;
|
||||
}
|
||||
|
||||
ir::Value spv::Context::createRuntimeArrayUniformBuffer(
|
||||
int descriptorSet, int binding, ir::Value elementType) {
|
||||
ir::Value spv::Context::createRuntimeArrayUniformBuffer(int descriptorSet,
|
||||
int binding,
|
||||
ir::Value elementType) {
|
||||
auto globals = Builder::createAppend(*this, layout.getOrCreateGlobals(*this));
|
||||
auto annotations =
|
||||
Builder::createAppend(*this, layout.getOrCreateAnnotations(*this));
|
||||
|
|
@ -602,8 +605,8 @@ ir::Value spv::Context::createInput(ir::Location loc, int index) {
|
|||
return result;
|
||||
}
|
||||
|
||||
ir::Value spv::Context::createAttr(ir::Location loc, int attrId,
|
||||
bool perVertex, bool flat) {
|
||||
ir::Value spv::Context::createAttr(ir::Location loc, int attrId, bool perVertex,
|
||||
bool flat) {
|
||||
auto &result = inputs[attrId];
|
||||
|
||||
if (result == nullptr) {
|
||||
|
|
|
|||
|
|
@ -1,29 +1,27 @@
|
|||
#include "gcn.hpp"
|
||||
|
||||
#include "Evaluator.hpp"
|
||||
#include "GcnInstruction.hpp"
|
||||
#include "SemanticInfo.hpp"
|
||||
#include "SpvConverter.hpp"
|
||||
#include "analyze.hpp"
|
||||
#include "dialect.hpp"
|
||||
#include "ir.hpp"
|
||||
#include "spv.hpp"
|
||||
#include "transform.hpp"
|
||||
|
||||
#include <rx/die.hpp>
|
||||
|
||||
#include <SPIRV/GlslangToSpv.h>
|
||||
#include <glslang/Include/ResourceLimits.h>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
#include <spirv-tools/libspirv.h>
|
||||
|
||||
#include <bit>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
#include "GcnInstruction.hpp"
|
||||
#include "dialect.hpp"
|
||||
#include "ir/Region.hpp"
|
||||
#include "ir/Value.hpp"
|
||||
|
||||
#include "spv.hpp"
|
||||
#include "transform.hpp"
|
||||
#include <glslang/Include/ResourceLimits.h>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
#include <SPIRV/GlslangToSpv.h>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <print>
|
||||
#include <spirv-tools/libspirv.h>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
|
@ -716,6 +714,13 @@ static ir::Value deserializeGcnRegion(
|
|||
ir::Value uint64TV = converter.getTypeUInt64();
|
||||
ir::Value sint64TV = converter.getTypeSInt64();
|
||||
|
||||
auto execTestSem =
|
||||
semInfo.findSemantic(ir::getInstructionId(ir::amdgpu::EXEC_TEST));
|
||||
|
||||
if (execTestSem == nullptr) {
|
||||
rx::die("Failed to find semantic of EXEC_TEST");
|
||||
}
|
||||
|
||||
unsigned currentOp = 0;
|
||||
|
||||
auto createOperandReadImpl = [&](ir::Location loc, gcn::Builder &builder,
|
||||
|
|
@ -917,14 +922,9 @@ static ir::Value deserializeGcnRegion(
|
|||
}
|
||||
};
|
||||
|
||||
auto createOperandWrite = [&](ir::Location loc, gcn::Builder &builder,
|
||||
const GcnOperand &op, ir::Value value,
|
||||
ir::Value lane = nullptr) {
|
||||
if (op.clamp || op.omod != 0) {
|
||||
value = builder.createValue(loc, ir::amdgpu::OMOD, value.getOperand(0),
|
||||
op.clamp, op.omod, value);
|
||||
}
|
||||
|
||||
auto createOperandWriteImpl = [&](ir::Location loc, gcn::Builder &builder,
|
||||
const GcnOperand &op, ir::Value value,
|
||||
ir::Value lane) {
|
||||
switch (op.kind) {
|
||||
case GcnOperand::Kind::Constant:
|
||||
case GcnOperand::Kind::Immediate:
|
||||
|
|
@ -966,6 +966,33 @@ static ir::Value deserializeGcnRegion(
|
|||
std::abort();
|
||||
};
|
||||
|
||||
auto createOperandWrite = [&](ir::Location loc, gcn::Builder &builder,
|
||||
bool injectExecTest, const GcnOperand &op,
|
||||
ir::Value value, ir::Value lane = nullptr) {
|
||||
if (op.clamp || op.omod != 0) {
|
||||
value = builder.createValue(loc, ir::amdgpu::OMOD, value.getOperand(0),
|
||||
op.clamp, op.omod, value);
|
||||
}
|
||||
|
||||
if (injectExecTest) {
|
||||
ir::Value testFailureValue;
|
||||
auto type = value.getOperand(0).getAsValue();
|
||||
if (op.kind == GcnOperand::Kind::Sgpr) {
|
||||
testFailureValue = converter.getNull(type);
|
||||
} else {
|
||||
testFailureValue = createOperandRead(loc, builder, type, op);
|
||||
}
|
||||
|
||||
auto exec =
|
||||
builder.createValue(loc, ir::amdgpu::EXEC_TEST,
|
||||
converter.getType(execTestSem->returnType));
|
||||
|
||||
value = builder.createSpvSelect(loc, type, exec, value, testFailureValue);
|
||||
}
|
||||
|
||||
return createOperandWriteImpl(loc, builder, op, value, lane);
|
||||
};
|
||||
|
||||
if (converter.body == nullptr) {
|
||||
converter.body =
|
||||
converter.create<ir::Region>(locBuilder.getLocation(address));
|
||||
|
|
@ -978,33 +1005,27 @@ static ir::Value deserializeGcnRegion(
|
|||
bodyRegion, address)
|
||||
.first;
|
||||
|
||||
auto execTestSem =
|
||||
semInfo.findSemantic(ir::getInstructionId(ir::amdgpu::EXEC_TEST));
|
||||
auto requiresExecTest = [&](ir::InstructionId instId) {
|
||||
switch (ir::getInstructionKind(instId)) {
|
||||
case ir::Kind::Sop2:
|
||||
case ir::Kind::Smrd:
|
||||
case ir::Kind::Sopc:
|
||||
case ir::Kind::Sopk:
|
||||
case ir::Kind::Sop1:
|
||||
case ir::Kind::Sopp:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (execTestSem == nullptr) {
|
||||
std::fprintf(stderr, "Failed to find semantic of EXEC_TEST\n");
|
||||
std::abort();
|
||||
}
|
||||
if (instId == ir::vop1::READFIRSTLANE_B32 ||
|
||||
instId == ir::vop2::READLANE_B32 || instId == ir::vop2::WRITELANE_B32 ||
|
||||
instId == ir::vop3::READFIRSTLANE_B32 ||
|
||||
instId == ir::vop3::READLANE_B32 || instId == ir::vop3::WRITELANE_B32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto injectExecTest = [&](ir::Location loc, gcn::Builder &builder,
|
||||
ir::Instruction point) {
|
||||
return;
|
||||
auto mergeBlock = builder.createSpvLabel(loc);
|
||||
gcn::Builder::createInsertBefore(converter, mergeBlock)
|
||||
.createSpvBranch(loc, mergeBlock);
|
||||
|
||||
auto instBlock =
|
||||
gcn::Builder::createInsertAfter(converter, point).createSpvLabel(loc);
|
||||
auto prependInstBuilder =
|
||||
gcn::Builder::createInsertBefore(converter, instBlock);
|
||||
|
||||
auto exec = prependInstBuilder.createValue(
|
||||
loc, ir::amdgpu::EXEC_TEST, converter.getType(execTestSem->returnType));
|
||||
|
||||
prependInstBuilder.createSpvSelectionMerge(loc, mergeBlock,
|
||||
ir::spv::SelectionControl::None);
|
||||
prependInstBuilder.createSpvBranchConditional(loc, exec, instBlock,
|
||||
mergeBlock);
|
||||
return true;
|
||||
};
|
||||
|
||||
std::vector<std::uint64_t> workList;
|
||||
|
|
@ -1050,6 +1071,9 @@ static ir::Value deserializeGcnRegion(
|
|||
auto builder = converter.createBuilder(instRegion, bodyRegion, instStart);
|
||||
auto instrBegin = builder.getInsertionPoint();
|
||||
|
||||
auto injectExecTest =
|
||||
requiresExecTest(ir::getInstructionId(isaInst.kind, isaInst.op));
|
||||
|
||||
auto variablesBuilder =
|
||||
gcn::Builder::createAppend(converter, converter.localVariables);
|
||||
|
||||
|
|
@ -1085,7 +1109,7 @@ static ir::Value deserializeGcnRegion(
|
|||
if (isaInst == ir::sop1::SWAPPC_B64) {
|
||||
auto target =
|
||||
createOperandRead(loc, builder, uint64TV, isaInst.getOperand(1));
|
||||
createOperandWrite(loc, builder, isaInst.getOperand(0),
|
||||
createOperandWrite(loc, builder, injectExecTest, isaInst.getOperand(0),
|
||||
converter.imm64(instAddress));
|
||||
branchesToUnknown.push_back(builder.createInstruction(
|
||||
loc, ir::Kind::AmdGpu, ir::amdgpu::BRANCH, target));
|
||||
|
|
@ -1093,7 +1117,7 @@ static ir::Value deserializeGcnRegion(
|
|||
}
|
||||
|
||||
if (isaInst == ir::sop1::GETPC_B64) {
|
||||
createOperandWrite(loc, builder, isaInst.getOperand(0),
|
||||
createOperandWrite(loc, builder, injectExecTest, isaInst.getOperand(0),
|
||||
converter.imm64(instAddress));
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1164,7 +1188,7 @@ static ir::Value deserializeGcnRegion(
|
|||
srcIndex = builder.createSpvSelect(loc, uint32TV, srcInBounds, srcIndex,
|
||||
converter.imm32(0));
|
||||
createOperandWrite(
|
||||
loc, builder, isaInst.getOperand(0),
|
||||
loc, builder, injectExecTest, isaInst.getOperand(0),
|
||||
converter.readReg(
|
||||
loc, builder,
|
||||
(isaInst == ir::sop1::MOVRELS_B64 ? uint64TV : uint32TV),
|
||||
|
|
@ -1224,12 +1248,7 @@ static ir::Value deserializeGcnRegion(
|
|||
auto regTypeValue = is64Bit ? uint64TV : uint32TV;
|
||||
auto value =
|
||||
createOperandRead(loc, builder, regTypeValue, operands[1]);
|
||||
createOperandWrite(loc, builder, operands[0], value);
|
||||
|
||||
if (isaInst.kind == ir::Kind::Vop1 ||
|
||||
isaInst.kind == ir::Kind::Vop3) {
|
||||
injectExecTest(loc, builder, instrBegin);
|
||||
}
|
||||
createOperandWrite(loc, builder, injectExecTest, operands[0], value);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1249,7 +1268,6 @@ static ir::Value deserializeGcnRegion(
|
|||
inst.addOperand(createOperandRead(loc, paramBuilder, uint32TV, op));
|
||||
}
|
||||
|
||||
injectExecTest(loc, builder, instrBegin);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1297,7 +1315,8 @@ static ir::Value deserializeGcnRegion(
|
|||
loc, float32TV,
|
||||
createOperandRead(loc, builder, float32TV, isaInst.getOperand(2)));
|
||||
|
||||
createOperandWrite(loc, builder, isaInst.getOperand(0), rawValue);
|
||||
createOperandWrite(loc, builder, injectExecTest, isaInst.getOperand(0),
|
||||
rawValue);
|
||||
}
|
||||
|
||||
continue;
|
||||
|
|
@ -1359,7 +1378,7 @@ static ir::Value deserializeGcnRegion(
|
|||
}
|
||||
|
||||
if (resultOperand) {
|
||||
createOperandWrite(loc, builder, *resultOperand, inst);
|
||||
createOperandWrite(loc, builder, injectExecTest, *resultOperand, inst);
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; auto &op : operands) {
|
||||
|
|
@ -1373,25 +1392,8 @@ static ir::Value deserializeGcnRegion(
|
|||
auto paramType = converter.getType(params[opIndex].type);
|
||||
|
||||
auto value = builder.createSpvLoad(loc, paramType, arg);
|
||||
createOperandWrite(loc, builder, op, value);
|
||||
createOperandWrite(loc, builder, injectExecTest, op, value);
|
||||
}
|
||||
|
||||
if (isaInst.kind == ir::Kind::Sop2 || isaInst.kind == ir::Kind::Sopk ||
|
||||
isaInst.kind == ir::Kind::Smrd || isaInst.kind == ir::Kind::Sop1 ||
|
||||
isaInst.kind == ir::Kind::Sopc || isaInst.kind == ir::Kind::Sopp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isaInst == ir::vop1::READFIRSTLANE_B32 ||
|
||||
isaInst == ir::vop2::READLANE_B32 ||
|
||||
isaInst == ir::vop2::WRITELANE_B32 ||
|
||||
isaInst == ir::vop3::READFIRSTLANE_B32 ||
|
||||
isaInst == ir::vop3::READLANE_B32 ||
|
||||
isaInst == ir::vop3::WRITELANE_B32) {
|
||||
continue;
|
||||
}
|
||||
|
||||
injectExecTest(loc, builder, instrBegin);
|
||||
}
|
||||
|
||||
converter.analysis.invalidateAll();
|
||||
|
|
|
|||
Loading…
Reference in a new issue