[dxbc] Implemented samplepos instruction

Required by Fallout 4, among other games.
This commit is contained in:
Philip Rebohle 2018-03-12 12:25:10 +01:00
parent b17568deba
commit 3d0aad705d
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
6 changed files with 342 additions and 63 deletions

View File

@ -103,6 +103,9 @@ namespace dxvk {
case DxbcInstClass::TextureQueryMs:
return this->emitTextureQueryMs(ins);
case DxbcInstClass::TextureQueryMsPos:
return this->emitTextureQueryMsPos(ins);
case DxbcInstClass::TextureFetch:
return this->emitTextureFetch(ins);
@ -2546,14 +2549,9 @@ namespace dxvk {
}
if (resinfoType == DxbcResinfoType::RcpFloat) {
const uint32_t typeId = getVectorTypeId(imageSize.type);
const uint32_t one = m_module.constf32(1.0f);
std::array<uint32_t, 4> constIds = { one, one, one, one };
imageSize.id = m_module.opFDiv(typeId,
m_module.constComposite(typeId,
imageSize.type.ccount, constIds.data()),
imageSize.id = m_module.opFDiv(
getVectorTypeId(imageSize.type),
m_module.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f),
imageSize.id);
}
@ -2657,6 +2655,66 @@ namespace dxvk {
}
void DxbcCompiler::emitTextureQueryMsPos(const DxbcShaderInstruction& ins) {
// samplepos has three operands:
// (dst0) The destination register
// (src0) Resource to query
// (src1) Sample index
// TODO Check if resource is bound
if (m_samplePositions == 0)
m_samplePositions = emitSamplePosArray();
// The lookup index is qual to the sample count plus the
// sample index, or 0 if the resource cannot be queried.
DxbcRegisterValue sampleCount = emitQueryTextureSamples(ins.src[0]);
DxbcRegisterValue sampleIndex = emitRegisterLoad(
ins.src[1], DxbcRegMask(true, false, false, false));
uint32_t lookupIndex = m_module.opIAdd(
getVectorTypeId(sampleCount.type),
sampleCount.id, sampleIndex.id);
// Validate the parameters
uint32_t sampleCountValid = m_module.opULessThanEqual(
m_module.defBoolType(),
sampleCount.id,
m_module.constu32(16));
uint32_t sampleIndexValid = m_module.opULessThan(
m_module.defBoolType(),
sampleIndex.id,
sampleCount.id);
// If the lookup cannot be performed, set the lookup
// index to zero, which will return a zero vector.
lookupIndex = m_module.opSelect(
getVectorTypeId(sampleCount.type),
m_module.opLogicalAnd(
m_module.defBoolType(),
sampleCountValid,
sampleIndexValid),
lookupIndex,
m_module.constu32(0));
// Load sample pos vector and write the masked
// components to the destination register.
DxbcRegisterPointer samplePos;
samplePos.type.ctype = DxbcScalarType::Float32;
samplePos.type.ccount = 4;
samplePos.id = m_module.opAccessChain(
m_module.defPointerType(
getVectorTypeId(samplePos.type),
spv::StorageClassPrivate),
m_samplePositions, 1, &lookupIndex);
emitRegisterStore(ins.dst[0],
emitRegisterSwizzle(
emitValueLoad(samplePos),
ins.src[0].swizzle,
ins.dst[0].mask));
}
void DxbcCompiler::emitTextureFetch(const DxbcShaderInstruction& ins) {
// ld has three operands:
// (dst0) The destination register
@ -3608,43 +3666,6 @@ namespace dxvk {
}
DxbcRegisterValue DxbcCompiler::emitBuildZero(
DxbcScalarType type) {
DxbcRegisterValue result;
result.type.ctype = type;
result.type.ccount = 1;
switch (type) {
case DxbcScalarType::Float32: result.id = m_module.constf32(0.0f); break;
case DxbcScalarType::Uint32: result.id = m_module.constu32(0); break;
case DxbcScalarType::Sint32: result.id = m_module.consti32(0); break;
default: throw DxvkError("DxbcCompiler: Invalid scalar type");
}
return result;
}
DxbcRegisterValue DxbcCompiler::emitBuildZeroVec(
DxbcVectorType type) {
const DxbcRegisterValue scalar = emitBuildZero(type.ctype);
if (type.ccount == 1)
return scalar;
const std::array<uint32_t, 4> zeroIds = {{
scalar.id, scalar.id, scalar.id, scalar.id,
}};
DxbcRegisterValue result;
result.type = type;
result.id = m_module.constComposite(
getVectorTypeId(result.type),
zeroIds.size(), zeroIds.data());
return result;
}
DxbcRegisterValue DxbcCompiler::emitRegisterBitcast(
DxbcRegisterValue srcValue,
DxbcScalarType dstType) {
@ -5688,7 +5709,67 @@ namespace dxvk {
return varId;
}
uint32_t DxbcCompiler::emitSamplePosArray() {
const std::array<uint32_t, 32> samplePosVectors = {{
// Invalid sample count / unbound resource
m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f),
// VK_SAMPLE_COUNT_1_BIT
m_module.constvec4f32(0.5f, 0.5f, 0.0f, 0.0f),
// VK_SAMPLE_COUNT_2_BIT
m_module.constvec4f32(0.25f, 0.25f, 0.0f, 0.0f),
m_module.constvec4f32(0.75f, 0.75f, 0.0f, 0.0f),
// VK_SAMPLE_COUNT_4_BIT
m_module.constvec4f32(0.375f, 0.125f, 0.0f, 0.0f),
m_module.constvec4f32(0.785f, 0.375f, 0.0f, 0.0f),
m_module.constvec4f32(0.125f, 0.625f, 0.0f, 0.0f),
m_module.constvec4f32(0.625f, 0.875f, 0.0f, 0.0f),
// VK_SAMPLE_COUNT_8_BIT
m_module.constvec4f32(0.5625f, 0.3125f, 0.0f, 0.0f),
m_module.constvec4f32(0.4375f, 0.6875f, 0.0f, 0.0f),
m_module.constvec4f32(0.8125f, 0.5625f, 0.0f, 0.0f),
m_module.constvec4f32(0.3125f, 0.1875f, 0.0f, 0.0f),
m_module.constvec4f32(0.1875f, 0.8125f, 0.0f, 0.0f),
m_module.constvec4f32(0.0625f, 0.4375f, 0.0f, 0.0f),
m_module.constvec4f32(0.6875f, 0.9375f, 0.0f, 0.0f),
m_module.constvec4f32(0.9375f, 0.0625f, 0.0f, 0.0f),
// VK_SAMPLE_COUNT_16_BIT
m_module.constvec4f32(0.5625f, 0.5625f, 0.0f, 0.0f),
m_module.constvec4f32(0.4375f, 0.3125f, 0.0f, 0.0f),
m_module.constvec4f32(0.3125f, 0.6250f, 0.0f, 0.0f),
m_module.constvec4f32(0.7500f, 0.4375f, 0.0f, 0.0f),
m_module.constvec4f32(0.1875f, 0.3750f, 0.0f, 0.0f),
m_module.constvec4f32(0.6250f, 0.8125f, 0.0f, 0.0f),
m_module.constvec4f32(0.8125f, 0.6875f, 0.0f, 0.0f),
m_module.constvec4f32(0.6875f, 0.1875f, 0.0f, 0.0f),
m_module.constvec4f32(0.3750f, 0.8750f, 0.0f, 0.0f),
m_module.constvec4f32(0.5000f, 0.0625f, 0.0f, 0.0f),
m_module.constvec4f32(0.2500f, 0.1250f, 0.0f, 0.0f),
m_module.constvec4f32(0.1250f, 0.7500f, 0.0f, 0.0f),
m_module.constvec4f32(0.0000f, 0.5000f, 0.0f, 0.0f),
m_module.constvec4f32(0.9375f, 0.2500f, 0.0f, 0.0f),
m_module.constvec4f32(0.8750f, 0.9375f, 0.0f, 0.0f),
m_module.constvec4f32(0.0625f, 0.0000f, 0.0f, 0.0f),
}};
uint32_t arrayTypeId = getArrayTypeId({
DxbcScalarType::Float32, 4,
samplePosVectors.size() });
uint32_t samplePosArray = m_module.constComposite(
arrayTypeId,
samplePosVectors.size(),
samplePosVectors.data());
uint32_t varId = m_module.newVarInit(
m_module.defPointerType(arrayTypeId, spv::StorageClassPrivate),
spv::StorageClassPrivate, samplePosArray);
m_module.setDebugName(varId, "g_sample_pos");
return varId;
}
uint32_t DxbcCompiler::emitNewVariable(const DxbcRegisterInfo& info) {
const uint32_t ptrTypeId = this->getPointerTypeId(info);
return m_module.newVar(ptrTypeId, info.sclass);

View File

@ -393,6 +393,11 @@ namespace dxvk {
// an array of four-component uint32 vectors.
uint32_t m_immConstBuf = 0;
///////////////////////////////////////////////////
// Sample pos array. If defined, this iis an array
// of 32 four-component float vectors.
uint32_t m_samplePositions = 0;
////////////////////////////////////////////
// Struct type used for UAV counter buffers
uint32_t m_uavCtrStructType = 0;
@ -589,6 +594,9 @@ namespace dxvk {
void emitTextureQueryMs(
const DxbcShaderInstruction& ins);
void emitTextureQueryMsPos(
const DxbcShaderInstruction& ins);
void emitTextureFetch(
const DxbcShaderInstruction& ins);
@ -676,12 +684,6 @@ namespace dxvk {
int32_t w,
const DxbcRegMask& writeMask);
DxbcRegisterValue emitBuildZero(
DxbcScalarType type);
DxbcRegisterValue emitBuildZeroVec(
DxbcVectorType type);
/////////////////////////////////////////
// Generic register manipulation methods
DxbcRegisterValue emitRegisterBitcast(
@ -934,6 +936,8 @@ namespace dxvk {
DxbcCompilerHsForkJoinPhase emitNewHullShaderForkJoinPhase();
uint32_t emitSamplePosArray();
///////////////////////////////
// Variable definition methods
uint32_t emitNewVariable(

View File

@ -553,7 +553,11 @@ namespace dxvk {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} },
/* SamplePos */
{ },
{ 3, DxbcInstClass::TextureQueryMsPos, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* SampleInfo */
{ 2, DxbcInstClass::TextureQueryMs, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },

View File

@ -47,6 +47,7 @@ namespace dxvk {
TextureQuery, ///< Texture query instruction
TextureQueryLod, ///< Texture LOD query instruction
TextureQueryMs, ///< Multisample texture query
TextureQueryMsPos, ///< Sample position query
TextureFetch, ///< Texture fetch instruction
TextureGather, ///< Texture gather instruction
TextureSample, ///< Texture sampling instruction

View File

@ -224,6 +224,84 @@ namespace dxvk {
}
uint32_t SpirvModule::constvec4i32(
int32_t x,
int32_t y,
int32_t z,
int32_t w) {
uint32_t scalarTypeId = this->defIntType(32, 1);
uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4);
uint32_t resultId = this->allocateId();
uint32_t xConst = this->consti32(x);
uint32_t yConst = this->consti32(y);
uint32_t zConst = this->consti32(z);
uint32_t wConst = this->consti32(w);
m_typeConstDefs.putIns (spv::OpConstantComposite, 7);
m_typeConstDefs.putWord (vectorTypeId);
m_typeConstDefs.putWord (resultId);
m_typeConstDefs.putWord (xConst);
m_typeConstDefs.putWord (yConst);
m_typeConstDefs.putWord (zConst);
m_typeConstDefs.putWord (wConst);
return resultId;
}
uint32_t SpirvModule::constvec4u32(
uint32_t x,
uint32_t y,
uint32_t z,
uint32_t w) {
uint32_t scalarTypeId = this->defIntType(32, 0);
uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4);
uint32_t resultId = this->allocateId();
uint32_t xConst = this->constu32(x);
uint32_t yConst = this->constu32(y);
uint32_t zConst = this->constu32(z);
uint32_t wConst = this->constu32(w);
m_typeConstDefs.putIns (spv::OpConstantComposite, 7);
m_typeConstDefs.putWord (vectorTypeId);
m_typeConstDefs.putWord (resultId);
m_typeConstDefs.putWord (xConst);
m_typeConstDefs.putWord (yConst);
m_typeConstDefs.putWord (zConst);
m_typeConstDefs.putWord (wConst);
return resultId;
}
uint32_t SpirvModule::constvec4f32(
float x,
float y,
float z,
float w) {
uint32_t scalarTypeId = this->defFloatType(32);
uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4);
uint32_t resultId = this->allocateId();
uint32_t xConst = this->constf32(x);
uint32_t yConst = this->constf32(y);
uint32_t zConst = this->constf32(z);
uint32_t wConst = this->constf32(w);
m_typeConstDefs.putIns (spv::OpConstantComposite, 7);
m_typeConstDefs.putWord (vectorTypeId);
m_typeConstDefs.putWord (resultId);
m_typeConstDefs.putWord (xConst);
m_typeConstDefs.putWord (yConst);
m_typeConstDefs.putWord (zConst);
m_typeConstDefs.putWord (wConst);
return resultId;
}
uint32_t SpirvModule::constComposite(
uint32_t typeId,
uint32_t constCount,
@ -379,7 +457,7 @@ namespace dxvk {
uint32_t SpirvModule::defIntType(
uint32_t width,
uint32_t isSigned) {
std::array<uint32_t, 2> args = { width, isSigned };
std::array<uint32_t, 2> args = {{ width, isSigned }};
return this->defType(spv::OpTypeInt,
args.size(), args.data());
}
@ -387,7 +465,7 @@ namespace dxvk {
uint32_t SpirvModule::defFloatType(
uint32_t width) {
std::array<uint32_t, 1> args = { width };
std::array<uint32_t, 1> args = {{ width }};
return this->defType(spv::OpTypeFloat,
args.size(), args.data());
}
@ -396,10 +474,8 @@ namespace dxvk {
uint32_t SpirvModule::defVectorType(
uint32_t elementType,
uint32_t elementCount) {
std::array<uint32_t, 2> args = {
elementType,
elementCount
};
std::array<uint32_t, 2> args =
{{ elementType, elementCount }};
return this->defType(spv::OpTypeVector,
args.size(), args.data());
@ -409,10 +485,8 @@ namespace dxvk {
uint32_t SpirvModule::defMatrixType(
uint32_t columnType,
uint32_t columnCount) {
std::array<uint32_t, 2> args = {
columnType,
columnCount
};
std::array<uint32_t, 2> args =
{{ columnType, columnCount }};
return this->defType(spv::OpTypeMatrix,
args.size(), args.data());
@ -422,7 +496,7 @@ namespace dxvk {
uint32_t SpirvModule::defArrayType(
uint32_t typeId,
uint32_t length) {
std::array<uint32_t, 2> args = { typeId, length };
std::array<uint32_t, 2> args = {{ typeId, length }};
return this->defType(spv::OpTypeArray,
args.size(), args.data());
@ -2024,6 +2098,79 @@ namespace dxvk {
}
uint32_t SpirvModule::opLogicalEqual(
uint32_t resultType,
uint32_t operand1,
uint32_t operand2) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpLogicalEqual, 5);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(operand1);
m_code.putWord(operand2);
return resultId;
}
uint32_t SpirvModule::opLogicalNotEqual(
uint32_t resultType,
uint32_t operand1,
uint32_t operand2) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpLogicalNotEqual, 5);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(operand1);
m_code.putWord(operand2);
return resultId;
}
uint32_t SpirvModule::opLogicalAnd(
uint32_t resultType,
uint32_t operand1,
uint32_t operand2) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpLogicalAnd, 5);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(operand1);
m_code.putWord(operand2);
return resultId;
}
uint32_t SpirvModule::opLogicalOr(
uint32_t resultType,
uint32_t operand1,
uint32_t operand2) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpLogicalOr, 5);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(operand1);
m_code.putWord(operand2);
return resultId;
}
uint32_t SpirvModule::opLogicalNot(
uint32_t resultType,
uint32_t operand) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpLogicalNot, 4);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(operand);
return resultId;
}
uint32_t SpirvModule::opDot(
uint32_t resultType,
uint32_t vector1,

View File

@ -119,6 +119,24 @@ namespace dxvk {
uint32_t constf64(
double v);
uint32_t constvec4i32(
int32_t x,
int32_t y,
int32_t z,
int32_t w);
uint32_t constvec4u32(
uint32_t x,
uint32_t y,
uint32_t z,
uint32_t w);
uint32_t constvec4f32(
float x,
float y,
float z,
float w);
uint32_t constComposite(
uint32_t typeId,
uint32_t constCount,
@ -724,6 +742,30 @@ namespace dxvk {
uint32_t vector1,
uint32_t vector2);
uint32_t opLogicalEqual(
uint32_t resultType,
uint32_t operand1,
uint32_t operand2);
uint32_t opLogicalNotEqual(
uint32_t resultType,
uint32_t operand1,
uint32_t operand2);
uint32_t opLogicalAnd(
uint32_t resultType,
uint32_t operand1,
uint32_t operand2);
uint32_t opLogicalOr(
uint32_t resultType,
uint32_t operand1,
uint32_t operand2);
uint32_t opLogicalNot(
uint32_t resultType,
uint32_t operand);
uint32_t opDot(
uint32_t resultType,
uint32_t vector1,