[dxbc] Added result modifiers, simple add instruction

This commit is contained in:
Philip Rebohle 2017-11-17 11:41:56 +01:00
parent 4c0404d3c6
commit abc0e98761
6 changed files with 197 additions and 2 deletions

View File

@ -33,6 +33,9 @@ namespace dxvk {
case DxbcOpcode::DclTemps:
return this->dclTemps(ins);
case DxbcOpcode::Add:
return this->opAdd(ins);
case DxbcOpcode::Mov:
return this->opMov(ins);
@ -109,13 +112,27 @@ namespace dxvk {
}
void DxbcCompiler::opAdd(const DxbcInstruction& ins) {
auto dstOp = ins.operand(0);
auto srcOp1 = ins.operand(dstOp.length());
auto srcOp2 = ins.operand(dstOp.length() + srcOp1.length());
DxbcComponentMask mask = this->getDstOperandMask(dstOp);
DxbcValue src1 = this->loadOperand(srcOp1, mask, DxbcScalarType::Float32);
DxbcValue src2 = this->loadOperand(srcOp2, mask, DxbcScalarType::Float32);
DxbcValue val = m_gen->opAdd(src1, src2);
val = this->applyResultModifiers(val, ins.token().control());
this->storeOperand(dstOp, val, mask);
}
void DxbcCompiler::opMov(const DxbcInstruction& ins) {
auto dstOp = ins.operand(0);
auto srcOp = ins.operand(dstOp.length());
DxbcComponentMask mask = this->getDstOperandMask(dstOp);
DxbcValue value = this->loadOperand(srcOp, mask, DxbcScalarType::Float32);
value = this->applyResultModifiers(value, ins.token().control());
this->storeOperand(dstOp, value, mask);
}
@ -252,6 +269,15 @@ namespace dxvk {
}
DxbcValue DxbcCompiler::applyResultModifiers(
DxbcValue value,
DxbcOpcodeControl control) {
if (control.saturateBit())
value = m_gen->opSaturate(value);
return value;
}
DxbcValue DxbcCompiler::loadOperand(
const DxbcOperand& operand,
DxbcComponentMask dstMask,
@ -267,16 +293,22 @@ namespace dxvk {
result = m_gen->defConstVector(
operand.imm32(0), operand.imm32(1),
operand.imm32(2), operand.imm32(3));
result = m_gen->regExtract(result, dstMask);
} else {
throw DxvkError(str::format(
"DxbcCompiler::loadOperand [imm32]: Invalid number of components: ",
token.numComponents()));
}
result = m_gen->regExtract(result, dstMask);
result = m_gen->regCast(result, DxbcValueType(
dstType, result.type.componentCount));
} else {
result = m_gen->regLoad(this->getOperandPtr(operand));
// Cast register to requested type
result = m_gen->regCast(result, DxbcValueType(
dstType, result.type.componentCount));
// Apply the source operand swizzle
if (token.numComponents() == 4)
result = this->selectOperandComponents(token, result, dstMask);

View File

@ -36,6 +36,9 @@ namespace dxvk {
void dclTemps(
const DxbcInstruction& ins);
void opAdd(
const DxbcInstruction& ins);
void opMov(
const DxbcInstruction& ins);
@ -63,6 +66,10 @@ namespace dxvk {
DxbcValue value,
DxbcOperandModifiers modifiers);
DxbcValue applyResultModifiers(
DxbcValue value,
DxbcOpcodeControl control);
DxbcValue loadOperand(
const DxbcOperand& operand,
DxbcComponentMask dstMask,

View File

@ -11,6 +11,77 @@ namespace dxvk {
class DxbcOperand;
/**
* \brief Basic control info
*
* Parses instruction-specific control bits. Whether
* these are well defined depends on the instruction.
*/
class DxbcOpcodeControl {
public:
DxbcOpcodeControl() { }
DxbcOpcodeControl(uint32_t control)
: m_control(control) { }
/**
* \brief Saturation hint
*
* If set, the result of the given instruction
* is clamped to the [0..1] range.
*/
bool saturateBit() const {
return bit::extract(m_control, 2, 2) != 0;
}
/**
* \brief Precision hint
*/
bool preciseBit() const {
return bit::extract(m_control, 8, 11) != 0;
}
/**
* \brief Zero test
*
* For conditional instructions, this defines
* whether the test shall pass when the given
* operand is zero or non-zero.
*/
DxbcZeroTest zeroTest() const {
return static_cast<DxbcZeroTest>(
bit::extract(m_control, 7, 7));
}
/**
* \brief Resinfo return type
*
* Control bits specifically for
* the \c resinfo instruction.
*/
DxbcResinfoType resinfoType() const {
return static_cast<DxbcResinfoType>(
bit::extract(m_control, 0, 1));
}
/**
* \brief Sync flags
*
* Defines the exact operation of sync
* instructions in compute shaders.
*/
DxbcSyncFlags syncFlags() const {
return bit::extract(m_control, 0, 3);
}
private:
uint32_t m_control = 0;
};
/**
* \brief DXBC instruction token
*

View File

@ -432,4 +432,24 @@ namespace dxvk {
using DxbcOperandModifiers = Flags<DxbcOperandModifier>;
enum class DxbcZeroTest : uint32_t {
TestZ = 0,
TestNz = 1,
};
enum class DxbcResinfoType : uint32_t {
Float = 0,
RcpFloat = 1, // ?
Uint = 2,
};
enum class DxbcSyncFlag : uint32_t {
ThreadsInGroup = 0,
ThreadGroupSharedMemory = 1,
UavMemoryGroup = 2,
UavMemoryGlobal = 3,
};
using DxbcSyncFlags = Flags<DxbcSyncFlag>;
}

View File

@ -565,6 +565,55 @@ namespace dxvk {
}
uint32_t SpirvModule::opIAdd(
uint32_t resultType,
uint32_t a,
uint32_t b) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpIAdd, 5);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(a);
m_code.putWord(b);
return resultId;
}
uint32_t SpirvModule::opFAdd(
uint32_t resultType,
uint32_t a,
uint32_t b) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpFAdd, 5);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(a);
m_code.putWord(b);
return resultId;
}
uint32_t SpirvModule::opFClamp(
uint32_t resultType,
uint32_t x,
uint32_t minVal,
uint32_t maxVal) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpExtInst, 8);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450FClamp);
m_code.putWord(x);
m_code.putWord(minVal);
m_code.putWord(maxVal);
return resultId;
}
uint32_t SpirvModule::opFunctionCall(
uint32_t resultType,
uint32_t functionId,

View File

@ -201,6 +201,22 @@ namespace dxvk {
uint32_t resultType,
uint32_t operand);
uint32_t opIAdd(
uint32_t resultType,
uint32_t a,
uint32_t b);
uint32_t opFAdd(
uint32_t resultType,
uint32_t a,
uint32_t b);
uint32_t opFClamp(
uint32_t resultType,
uint32_t x,
uint32_t minVal,
uint32_t maxVal);
uint32_t opFunctionCall(
uint32_t resultType,
uint32_t functionId,