mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-21 13:54:18 +01:00
[dxbc] Implemented f16 pack/unpack instructions
This commit is contained in:
parent
f93745adcf
commit
e740adfcb7
@ -60,12 +60,6 @@ namespace dxvk {
|
|||||||
case DxbcInstClass::CustomData:
|
case DxbcInstClass::CustomData:
|
||||||
return this->emitCustomData(ins);
|
return this->emitCustomData(ins);
|
||||||
|
|
||||||
case DxbcInstClass::ControlFlow:
|
|
||||||
return this->emitControlFlow(ins);
|
|
||||||
|
|
||||||
case DxbcInstClass::GeometryEmit:
|
|
||||||
return this->emitGeometryEmit(ins);
|
|
||||||
|
|
||||||
case DxbcInstClass::Atomic:
|
case DxbcInstClass::Atomic:
|
||||||
return this->emitAtomic(ins);
|
return this->emitAtomic(ins);
|
||||||
|
|
||||||
@ -87,6 +81,15 @@ namespace dxvk {
|
|||||||
case DxbcInstClass::BufferStore:
|
case DxbcInstClass::BufferStore:
|
||||||
return this->emitBufferStore(ins);
|
return this->emitBufferStore(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::ConvertFloat16:
|
||||||
|
return this->emitConvertFloat16(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::ControlFlow:
|
||||||
|
return this->emitControlFlow(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::GeometryEmit:
|
||||||
|
return this->emitGeometryEmit(ins);
|
||||||
|
|
||||||
case DxbcInstClass::TextureQuery:
|
case DxbcInstClass::TextureQuery:
|
||||||
return this->emitTextureQuery(ins);
|
return this->emitTextureQuery(ins);
|
||||||
|
|
||||||
@ -1368,7 +1371,7 @@ namespace dxvk {
|
|||||||
if (ins.dst[0].type != DxbcOperandType::Null
|
if (ins.dst[0].type != DxbcOperandType::Null
|
||||||
&& ins.dst[1].type != DxbcOperandType::Null
|
&& ins.dst[1].type != DxbcOperandType::Null
|
||||||
&& ins.dst[0].mask != ins.dst[1].mask) {
|
&& ins.dst[0].mask != ins.dst[1].mask) {
|
||||||
Logger::warn("DxbcCompiler: Umul with different destination masks not supported");
|
Logger::warn("DxbcCompiler: Idiv with different destination masks not supported");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1558,7 +1561,12 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitAtomic(const DxbcShaderInstruction& ins) {
|
void DxbcCompiler::emitAtomic(const DxbcShaderInstruction& ins) {
|
||||||
Logger::err("DxbcCompiler: emitAtomic not implemented");
|
switch (ins.op) {
|
||||||
|
default:
|
||||||
|
Logger::warn(str::format(
|
||||||
|
"DxbcCompiler: Unhandled instruction: ",
|
||||||
|
ins.op));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1753,6 +1761,75 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitConvertFloat16(const DxbcShaderInstruction& ins) {
|
||||||
|
// f32tof16 takes two operands:
|
||||||
|
// (dst0) Destination register as a uint32 vector
|
||||||
|
// (src0) Source register as a float32 vector
|
||||||
|
// f16tof32 takes two operands:
|
||||||
|
// (dst0) Destination register as a float32 vector
|
||||||
|
// (src0) Source register as a uint32 vector
|
||||||
|
const DxbcRegisterValue src = emitRegisterLoad(ins.src[0], ins.dst[0].mask);
|
||||||
|
|
||||||
|
// We handle both packing and unpacking here
|
||||||
|
const bool isPack = ins.op == DxbcOpcode::F32toF16;
|
||||||
|
|
||||||
|
// The conversion instructions do not map very well to the
|
||||||
|
// SPIR-V pack instructions, which operate on 2D vectors.
|
||||||
|
std::array<uint32_t, 4> scalarIds = {{ 0, 0, 0, 0 }};
|
||||||
|
std::array<uint32_t, 4> swizzleIds = {{ 0, 0, 0, 0 }};
|
||||||
|
|
||||||
|
uint32_t componentIndex = 0;
|
||||||
|
|
||||||
|
// These types are used in both pack and unpack operations
|
||||||
|
const uint32_t t_u32 = getVectorTypeId({ DxbcScalarType::Uint32, 1 });
|
||||||
|
const uint32_t t_f32 = getVectorTypeId({ DxbcScalarType::Float32, 1 });
|
||||||
|
const uint32_t t_f32v2 = getVectorTypeId({ DxbcScalarType::Float32, 2 });
|
||||||
|
|
||||||
|
// Constant zero-bit pattern, used for packing
|
||||||
|
const uint32_t zerof32 = isPack ? m_module.constf32(0.0f) : 0;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 4; i++) {
|
||||||
|
if (ins.dst[0].mask[i]) {
|
||||||
|
const uint32_t swizzleIndex = ins.src[0].swizzle[i];
|
||||||
|
|
||||||
|
// When extracting components from the source register, we must
|
||||||
|
// take into account that it it already swizzled and masked.
|
||||||
|
if (scalarIds[swizzleIndex] == 0) {
|
||||||
|
if (isPack) { // f32tof16
|
||||||
|
const std::array<uint32_t, 2> packIds =
|
||||||
|
{{ m_module.opCompositeExtract(t_f32, src.id, 1, &componentIndex), zerof32 }};
|
||||||
|
|
||||||
|
scalarIds[swizzleIndex] = m_module.opPackHalf2x16(t_u32,
|
||||||
|
m_module.opCompositeConstruct(t_f32v2, packIds.size(), packIds.data()));
|
||||||
|
} else { // f16tof32
|
||||||
|
const uint32_t zeroIndex = 0;
|
||||||
|
|
||||||
|
scalarIds[swizzleIndex] = m_module.opCompositeExtract(t_f32,
|
||||||
|
m_module.opUnpackHalf2x16(t_f32v2,
|
||||||
|
m_module.opCompositeExtract(t_u32, src.id, 1, &componentIndex)),
|
||||||
|
1, &zeroIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply write mask and source swizzle at the same time
|
||||||
|
swizzleIds[componentIndex++] = scalarIds[swizzleIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store result in the destination register
|
||||||
|
DxbcRegisterValue result;
|
||||||
|
result.type.ctype = ins.dst[0].dataType;
|
||||||
|
result.type.ccount = componentIndex;
|
||||||
|
result.id = componentIndex > 1
|
||||||
|
? m_module.opCompositeConstruct(
|
||||||
|
getVectorTypeId(result.type),
|
||||||
|
componentIndex, swizzleIds.data())
|
||||||
|
: swizzleIds[0];
|
||||||
|
|
||||||
|
emitRegisterStore(ins.dst[0], result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitTextureQuery(const DxbcShaderInstruction& ins) {
|
void DxbcCompiler::emitTextureQuery(const DxbcShaderInstruction& ins) {
|
||||||
// resinfo has three operands:
|
// resinfo has three operands:
|
||||||
// (dst0) The destination register
|
// (dst0) The destination register
|
||||||
@ -2833,10 +2910,9 @@ namespace dxvk {
|
|||||||
|
|
||||||
if (componentIds[swizzleIndex] == 0) {
|
if (componentIds[swizzleIndex] == 0) {
|
||||||
// Add the component offset to the element index
|
// Add the component offset to the element index
|
||||||
const uint32_t elementIndexAdjusted = swizzleIndex != 0
|
const uint32_t elementIndexAdjusted = m_module.opIAdd(
|
||||||
? m_module.opIAdd(getVectorTypeId(elementIndex.type),
|
getVectorTypeId(elementIndex.type), elementIndex.id,
|
||||||
elementIndex.id, m_module.consti32(swizzleIndex))
|
m_module.consti32(swizzleIndex));
|
||||||
: elementIndex.id;
|
|
||||||
|
|
||||||
// Load requested component from the buffer
|
// Load requested component from the buffer
|
||||||
componentIds[swizzleIndex] = [&] {
|
componentIds[swizzleIndex] = [&] {
|
||||||
@ -2876,7 +2952,6 @@ namespace dxvk {
|
|||||||
DxbcRegisterValue result;
|
DxbcRegisterValue result;
|
||||||
result.type.ctype = DxbcScalarType::Uint32;
|
result.type.ctype = DxbcScalarType::Uint32;
|
||||||
result.type.ccount = writeMask.setCount();
|
result.type.ccount = writeMask.setCount();
|
||||||
|
|
||||||
result.id = result.type.ccount > 1
|
result.id = result.type.ccount > 1
|
||||||
? m_module.opCompositeConstruct(getVectorTypeId(result.type),
|
? m_module.opCompositeConstruct(getVectorTypeId(result.type),
|
||||||
result.type.ccount, swizzleIds.data())
|
result.type.ccount, swizzleIds.data())
|
||||||
|
@ -410,6 +410,9 @@ namespace dxvk {
|
|||||||
void emitBufferStore(
|
void emitBufferStore(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitConvertFloat16(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitTextureQuery(
|
void emitTextureQuery(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
@ -586,9 +586,15 @@ namespace dxvk {
|
|||||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||||
} },
|
} },
|
||||||
/* F32toF16 */
|
/* F32toF16 */
|
||||||
{ },
|
{ 2, DxbcInstClass::ConvertFloat16, {
|
||||||
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||||
|
} },
|
||||||
/* F16toF32 */
|
/* F16toF32 */
|
||||||
{ },
|
{ 2, DxbcInstClass::ConvertFloat16, {
|
||||||
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
|
} },
|
||||||
/* UAddc */
|
/* UAddc */
|
||||||
{ },
|
{ },
|
||||||
/* USubb */
|
/* USubb */
|
||||||
|
@ -39,6 +39,7 @@ namespace dxvk {
|
|||||||
BufferQuery, ///< Buffer query instruction
|
BufferQuery, ///< Buffer query instruction
|
||||||
BufferLoad, ///< Structured or raw buffer load
|
BufferLoad, ///< Structured or raw buffer load
|
||||||
BufferStore, ///< Structured or raw buffer store
|
BufferStore, ///< Structured or raw buffer store
|
||||||
|
ConvertFloat16, ///< 16-bit float packing/unpacking
|
||||||
TextureQuery, ///< Texture query instruction
|
TextureQuery, ///< Texture query instruction
|
||||||
TextureFetch, ///< Texture fetch instruction
|
TextureFetch, ///< Texture fetch instruction
|
||||||
TextureSample, ///< Texture sampling instruction
|
TextureSample, ///< Texture sampling instruction
|
||||||
|
@ -1760,6 +1760,36 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opPackHalf2x16(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t operand) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpExtInst, 6);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(m_instExtGlsl450);
|
||||||
|
m_code.putWord(spv::GLSLstd450PackHalf2x16);
|
||||||
|
m_code.putWord(operand);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opUnpackHalf2x16(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t operand) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpExtInst, 6);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(m_instExtGlsl450);
|
||||||
|
m_code.putWord(spv::GLSLstd450UnpackHalf2x16);
|
||||||
|
m_code.putWord(operand);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvModule::opSelect(
|
uint32_t SpirvModule::opSelect(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t condition,
|
uint32_t condition,
|
||||||
|
@ -601,6 +601,14 @@ namespace dxvk {
|
|||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t operand);
|
uint32_t operand);
|
||||||
|
|
||||||
|
uint32_t opPackHalf2x16(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t operand);
|
||||||
|
|
||||||
|
uint32_t opUnpackHalf2x16(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t operand);
|
||||||
|
|
||||||
uint32_t opSelect(
|
uint32_t opSelect(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t condition,
|
uint32_t condition,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user