mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 05:52:11 +01:00
[dxbc] Added result modifiers, simple add instruction
This commit is contained in:
parent
4c0404d3c6
commit
abc0e98761
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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>;
|
||||
|
||||
}
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user