[dxbc] Implemented bfi and bfe instructions

This commit is contained in:
Philip Rebohle 2017-12-30 03:44:19 +01:00
parent 1373fe5fcc
commit f93745adcf
7 changed files with 196 additions and 5 deletions

View File

@ -72,6 +72,12 @@ namespace dxvk {
case DxbcInstClass::Barrier:
return this->emitBarrier(ins);
case DxbcInstClass::BitExtract:
return this->emitBitExtract(ins);
case DxbcInstClass::BitInsert:
return this->emitBitInsert(ins);
case DxbcInstClass::BufferQuery:
return this->emitBufferQuery(ins);
@ -996,6 +1002,13 @@ namespace dxvk {
src.at(0).id, src.at(1).id);
break;
case DxbcOpcode::Rcp: {
const std::array<float, 4> ones = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
dst.id = m_module.opFDiv(typeId,
emitBuildConstVecf32(ones.data(), ins.dst[0].mask).id,
src.at(0).id);
} break;
case DxbcOpcode::RoundNe:
dst.id = m_module.opRoundEven(
typeId, src.at(0).id);
@ -1591,6 +1604,53 @@ namespace dxvk {
}
void DxbcCompiler::emitBitExtract(const DxbcShaderInstruction& ins) {
// ibfe and ubfe take the following arguments:
// (dst0) The destination register
// (src0) Number of bits to extact
// (src1) Offset of the bits to extract
// (src2) Register to extract bits from
const bool isSigned = ins.op == DxbcOpcode::IBfe;
const DxbcRegisterValue bitCnt = emitRegisterLoad(ins.src[0], ins.dst[0].mask);
const DxbcRegisterValue bitOfs = emitRegisterLoad(ins.src[1], ins.dst[0].mask);
const DxbcRegisterValue src = emitRegisterLoad(ins.src[2], ins.dst[0].mask);
const uint32_t typeId = getVectorTypeId(src.type);
DxbcRegisterValue result;
result.type = src.type;
result.id = isSigned
? m_module.opBitFieldSExtract(typeId, result.id, bitOfs.id, bitCnt.id)
: m_module.opBitFieldUExtract(typeId, result.id, bitOfs.id, bitCnt.id);
emitRegisterStore(ins.dst[0], result);
}
void DxbcCompiler::emitBitInsert(const DxbcShaderInstruction& ins) {
// ibfe and ubfe take the following arguments:
// (dst0) The destination register
// (src0) Number of bits to extact
// (src1) Offset of the bits to extract
// (src2) Register to take bits from
// (src3) Register to replace bits in
const DxbcRegisterValue bitCnt = emitRegisterLoad(ins.src[0], ins.dst[0].mask);
const DxbcRegisterValue bitOfs = emitRegisterLoad(ins.src[1], ins.dst[0].mask);
const DxbcRegisterValue insert = emitRegisterLoad(ins.src[2], ins.dst[0].mask);
const DxbcRegisterValue base = emitRegisterLoad(ins.src[3], ins.dst[0].mask);
DxbcRegisterValue result;
result.type = base.type;
result.id = m_module.opBitFieldInsert(
getVectorTypeId(result.type),
base.id, insert.id, bitOfs.id, bitCnt.id);
emitRegisterStore(ins.dst[0], result);
}
void DxbcCompiler::emitBufferQuery(const DxbcShaderInstruction& ins) {
// bufinfo takes two arguments
// (dst0) The destination register
@ -2307,6 +2367,29 @@ namespace dxvk {
}
DxbcRegisterValue DxbcCompiler::emitBuildConstVecf32(
const float values[4],
const DxbcRegMask& writeMask) {
std::array<uint32_t, 4> ids = { 0, 0, 0, 0 };
uint32_t componentIndex = 0;
for (uint32_t i = 0; i < 4; i++) {
if (writeMask[i])
ids[componentIndex++] = m_module.constf32(values[i]);
}
DxbcRegisterValue result;
result.type.ctype = DxbcScalarType::Float32;
result.type.ccount = componentIndex;
result.id = componentIndex > 1
? m_module.constComposite(
getVectorTypeId(result.type),
componentIndex, ids.data())
: ids[0];
return result;
}
DxbcRegisterValue DxbcCompiler::emitRegisterBitcast(
DxbcRegisterValue srcValue,
DxbcScalarType dstType) {

View File

@ -395,6 +395,12 @@ namespace dxvk {
void emitBarrier(
const DxbcShaderInstruction& ins);
void emitBitExtract(
const DxbcShaderInstruction& ins);
void emitBitInsert(
const DxbcShaderInstruction& ins);
void emitBufferQuery(
const DxbcShaderInstruction& ins);
@ -445,6 +451,14 @@ namespace dxvk {
void emitControlFlow(
const DxbcShaderInstruction& ins);
////////////////////////////////////////////////
// Constant building methods. These are used to
// generate constant vectors that store the same
// value in each component.
DxbcRegisterValue emitBuildConstVecf32(
const float values[4],
const DxbcRegMask& writeMask);
/////////////////////////////////////////
// Generic register manipulation methods
DxbcRegisterValue emitRegisterBitcast(

View File

@ -581,7 +581,10 @@ namespace dxvk {
/* Gather4PoC */
{ },
/* Rcp */
{ },
{ 2, DxbcInstClass::VectorAlu, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} },
/* F32toF16 */
{ },
/* F16toF32 */
@ -599,11 +602,27 @@ namespace dxvk {
/* FirstBitShi */
{ },
/* UBfe */
{ },
{ 4, DxbcInstClass::BitExtract, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* IBfe */
{ },
{ 4, DxbcInstClass::BitExtract, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Sint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
} },
/* Bfi */
{ },
{ 5, DxbcInstClass::BitInsert, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* BfRev */
{ },
/* Swapc */

View File

@ -34,6 +34,8 @@ namespace dxvk {
GeometryEmit, ///< Special geometry shader instructions
Atomic, ///< Atomic operations
Barrier, ///< Execution or memory barrier
BitExtract, ///< Bit field extract operations
BitInsert, ///< Bit field insert operations
BufferQuery, ///< Buffer query instruction
BufferLoad, ///< Structured or raw buffer load
BufferStore, ///< Structured or raw buffer store

View File

@ -604,6 +604,59 @@ namespace dxvk {
}
uint32_t SpirvModule::opBitFieldInsert(
uint32_t resultType,
uint32_t base,
uint32_t insert,
uint32_t offset,
uint32_t count) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpBitFieldInsert, 7);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(base);
m_code.putWord(insert);
m_code.putWord(offset);
m_code.putWord(count);
return resultId;
}
uint32_t SpirvModule::opBitFieldSExtract(
uint32_t resultType,
uint32_t base,
uint32_t offset,
uint32_t count) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpBitFieldSExtract, 6);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(base);
m_code.putWord(offset);
m_code.putWord(count);
return resultId;
}
uint32_t SpirvModule::opBitFieldUExtract(
uint32_t resultType,
uint32_t base,
uint32_t offset,
uint32_t count) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpBitFieldUExtract, 6);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(base);
m_code.putWord(offset);
m_code.putWord(count);
return resultId;
}
uint32_t SpirvModule::opBitwiseAnd(
uint32_t resultType,
uint32_t operand1,

View File

@ -237,6 +237,25 @@ namespace dxvk {
uint32_t resultType,
uint32_t operand);
uint32_t opBitFieldInsert(
uint32_t resultType,
uint32_t base,
uint32_t insert,
uint32_t offset,
uint32_t count);
uint32_t opBitFieldSExtract(
uint32_t resultType,
uint32_t base,
uint32_t offset,
uint32_t count);
uint32_t opBitFieldUExtract(
uint32_t resultType,
uint32_t base,
uint32_t offset,
uint32_t count);
uint32_t opBitwiseAnd(
uint32_t resultType,
uint32_t operand1,

View File

@ -47,7 +47,8 @@ int WINAPI WinMain(HINSTANCE hInstance,
"Shader", nullptr, nullptr,
str::fromws(entryPoint).c_str(),
str::fromws(target).c_str(),
0, 0, &binary, &errors);
D3DCOMPILE_OPTIMIZATION_LEVEL3,
0, &binary, &errors);
if (FAILED(hr)) {
if (errors != nullptr)