mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-11-29 10:24:10 +01:00
[dxbc] Implemented operand modifiers and load/store stuff
This commit is contained in:
parent
901abe4356
commit
5d26f0fb0c
135
include/spirv/GLSL.std.450.hpp
Normal file
135
include/spirv/GLSL.std.450.hpp
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef GLSLstd450_HPP
|
||||
#define GLSLstd450_HPP
|
||||
|
||||
namespace spv {
|
||||
|
||||
static const int GLSLstd450Version = 100;
|
||||
static const int GLSLstd450Revision = 3;
|
||||
|
||||
enum GLSLstd450 {
|
||||
GLSLstd450Bad = 0, // Don't use
|
||||
|
||||
GLSLstd450Round = 1,
|
||||
GLSLstd450RoundEven = 2,
|
||||
GLSLstd450Trunc = 3,
|
||||
GLSLstd450FAbs = 4,
|
||||
GLSLstd450SAbs = 5,
|
||||
GLSLstd450FSign = 6,
|
||||
GLSLstd450SSign = 7,
|
||||
GLSLstd450Floor = 8,
|
||||
GLSLstd450Ceil = 9,
|
||||
GLSLstd450Fract = 10,
|
||||
|
||||
GLSLstd450Radians = 11,
|
||||
GLSLstd450Degrees = 12,
|
||||
GLSLstd450Sin = 13,
|
||||
GLSLstd450Cos = 14,
|
||||
GLSLstd450Tan = 15,
|
||||
GLSLstd450Asin = 16,
|
||||
GLSLstd450Acos = 17,
|
||||
GLSLstd450Atan = 18,
|
||||
GLSLstd450Sinh = 19,
|
||||
GLSLstd450Cosh = 20,
|
||||
GLSLstd450Tanh = 21,
|
||||
GLSLstd450Asinh = 22,
|
||||
GLSLstd450Acosh = 23,
|
||||
GLSLstd450Atanh = 24,
|
||||
GLSLstd450Atan2 = 25,
|
||||
|
||||
GLSLstd450Pow = 26,
|
||||
GLSLstd450Exp = 27,
|
||||
GLSLstd450Log = 28,
|
||||
GLSLstd450Exp2 = 29,
|
||||
GLSLstd450Log2 = 30,
|
||||
GLSLstd450Sqrt = 31,
|
||||
GLSLstd450InverseSqrt = 32,
|
||||
|
||||
GLSLstd450Determinant = 33,
|
||||
GLSLstd450MatrixInverse = 34,
|
||||
|
||||
GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
|
||||
GLSLstd450ModfStruct = 36, // no OpVariable operand
|
||||
GLSLstd450FMin = 37,
|
||||
GLSLstd450UMin = 38,
|
||||
GLSLstd450SMin = 39,
|
||||
GLSLstd450FMax = 40,
|
||||
GLSLstd450UMax = 41,
|
||||
GLSLstd450SMax = 42,
|
||||
GLSLstd450FClamp = 43,
|
||||
GLSLstd450UClamp = 44,
|
||||
GLSLstd450SClamp = 45,
|
||||
GLSLstd450FMix = 46,
|
||||
GLSLstd450IMix = 47, // Reserved
|
||||
GLSLstd450Step = 48,
|
||||
GLSLstd450SmoothStep = 49,
|
||||
|
||||
GLSLstd450Fma = 50,
|
||||
GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
|
||||
GLSLstd450FrexpStruct = 52, // no OpVariable operand
|
||||
GLSLstd450Ldexp = 53,
|
||||
|
||||
GLSLstd450PackSnorm4x8 = 54,
|
||||
GLSLstd450PackUnorm4x8 = 55,
|
||||
GLSLstd450PackSnorm2x16 = 56,
|
||||
GLSLstd450PackUnorm2x16 = 57,
|
||||
GLSLstd450PackHalf2x16 = 58,
|
||||
GLSLstd450PackDouble2x32 = 59,
|
||||
GLSLstd450UnpackSnorm2x16 = 60,
|
||||
GLSLstd450UnpackUnorm2x16 = 61,
|
||||
GLSLstd450UnpackHalf2x16 = 62,
|
||||
GLSLstd450UnpackSnorm4x8 = 63,
|
||||
GLSLstd450UnpackUnorm4x8 = 64,
|
||||
GLSLstd450UnpackDouble2x32 = 65,
|
||||
|
||||
GLSLstd450Length = 66,
|
||||
GLSLstd450Distance = 67,
|
||||
GLSLstd450Cross = 68,
|
||||
GLSLstd450Normalize = 69,
|
||||
GLSLstd450FaceForward = 70,
|
||||
GLSLstd450Reflect = 71,
|
||||
GLSLstd450Refract = 72,
|
||||
|
||||
GLSLstd450FindILsb = 73,
|
||||
GLSLstd450FindSMsb = 74,
|
||||
GLSLstd450FindUMsb = 75,
|
||||
|
||||
GLSLstd450InterpolateAtCentroid = 76,
|
||||
GLSLstd450InterpolateAtSample = 77,
|
||||
GLSLstd450InterpolateAtOffset = 78,
|
||||
|
||||
GLSLstd450NMin = 79,
|
||||
GLSLstd450NMax = 80,
|
||||
GLSLstd450NClamp = 81,
|
||||
|
||||
GLSLstd450Count
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // #ifndef GLSLstd450_HPP
|
@ -33,6 +33,12 @@ namespace dxvk {
|
||||
case DxbcOpcode::DclTemps:
|
||||
return this->dclTemps(ins);
|
||||
|
||||
case DxbcOpcode::Mov:
|
||||
return this->opMov(ins);
|
||||
|
||||
case DxbcOpcode::Ret:
|
||||
return this->opRet(ins);
|
||||
|
||||
default:
|
||||
Logger::err(str::format(
|
||||
"DxbcCompiler::processInstruction: Unhandled opcode: ",
|
||||
@ -52,7 +58,49 @@ namespace dxvk {
|
||||
|
||||
|
||||
void DxbcCompiler::dclInterfaceVar(const DxbcInstruction& ins) {
|
||||
auto op = ins.operand(0);
|
||||
auto opcode = ins.token().opcode();
|
||||
|
||||
switch (op.token().type()) {
|
||||
case DxbcOperandType::Input:
|
||||
case DxbcOperandType::Output: {
|
||||
uint32_t regId = 0;
|
||||
uint32_t regDim = 0;
|
||||
|
||||
if (op.token().indexDimension() == 1) {
|
||||
regId = op.index(0).immPart();
|
||||
} else if (op.token().indexDimension() == 2) {
|
||||
regDim = op.index(0).immPart();
|
||||
regId = op.index(1).immPart();
|
||||
} else {
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::dclInterfaceVar: Invalid index dimension: ",
|
||||
op.token().indexDimension()));
|
||||
}
|
||||
|
||||
const bool hasSv =
|
||||
opcode == DxbcOpcode::DclInputSgv
|
||||
|| opcode == DxbcOpcode::DclInputSiv
|
||||
|| opcode == DxbcOpcode::DclInputPsSgv
|
||||
|| opcode == DxbcOpcode::DclInputPsSiv
|
||||
|| opcode == DxbcOpcode::DclOutputSgv
|
||||
|| opcode == DxbcOpcode::DclOutputSiv;
|
||||
|
||||
DxbcSystemValue sv = DxbcSystemValue::None;
|
||||
|
||||
if (hasSv)
|
||||
sv = ins.readEnum<DxbcSystemValue>(op.length());
|
||||
|
||||
m_gen->dclInterfaceVar(
|
||||
op.token().type(), regId, regDim,
|
||||
op.token().componentMask(), sv);
|
||||
} break;
|
||||
|
||||
default:
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::dclInterfaceVar: Unhandled operand type: ",
|
||||
op.token().type()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -60,4 +108,207 @@ namespace dxvk {
|
||||
m_gen->dclTemps(ins.arg(0));
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
this->storeOperand(dstOp, value, mask);
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::opRet(const DxbcInstruction& ins) {
|
||||
m_gen->fnReturn();
|
||||
}
|
||||
|
||||
|
||||
DxbcComponentMask DxbcCompiler::getDstOperandMask(const DxbcOperand& operand) {
|
||||
const DxbcOperandToken token = operand.token();
|
||||
|
||||
if (token.numComponents() == 1) {
|
||||
return DxbcComponentMask(true, false, false, false);
|
||||
} else if (token.numComponents() == 4) {
|
||||
switch (token.selectionMode()) {
|
||||
case DxbcComponentSelectionMode::Mask:
|
||||
return token.componentMask();
|
||||
|
||||
case DxbcComponentSelectionMode::Select1:
|
||||
return token.componentSelection();
|
||||
|
||||
default:
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::getDstOperandMask: Invalid component selection mode: ",
|
||||
token.selectionMode()));
|
||||
}
|
||||
} else {
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::getDstOperandMask: Invalid component count: ",
|
||||
token.numComponents()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxbcPointer DxbcCompiler::getTempOperandPtr(const DxbcOperand& operand) {
|
||||
if (operand.token().indexDimension() != 1) {
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::getTempOperandPtr: Invalid index dimension: ",
|
||||
operand.token().indexDimension()));
|
||||
}
|
||||
|
||||
if (operand.token().indexRepresentation(0) != DxbcOperandIndexRepresentation::Imm32) {
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::getTempOperandPtr: Invalid index representation: ",
|
||||
operand.token().indexRepresentation(0)));
|
||||
}
|
||||
|
||||
return m_gen->ptrTempReg(operand.index(0).immPart());
|
||||
}
|
||||
|
||||
|
||||
DxbcPointer DxbcCompiler::getInterfaceOperandPtr(const DxbcOperand& operand) {
|
||||
const uint32_t indexDim = operand.token().indexDimension();
|
||||
|
||||
// Vertex index ID is unused if the index dimension
|
||||
// is 1. The element index is always the last index.
|
||||
// const uint32_t vIndexId = 0;
|
||||
const uint32_t eIndexId = indexDim - 1;
|
||||
|
||||
if (operand.token().indexRepresentation(eIndexId) != DxbcOperandIndexRepresentation::Imm32) {
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::getInterfaceOperandPtr: Invalid element index representation: ",
|
||||
operand.token().indexRepresentation(eIndexId)));
|
||||
}
|
||||
|
||||
if (indexDim == 1) {
|
||||
return m_gen->ptrInterfaceVar(
|
||||
operand.token().type(),
|
||||
operand.index(eIndexId).immPart());
|
||||
} else {
|
||||
// TODO implement index dimension 2
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::getInterfaceOperandPtr: Invalid index dimension: ",
|
||||
indexDim));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxbcPointer DxbcCompiler::getOperandPtr(const DxbcOperand& operand) {
|
||||
switch (operand.token().type()) {
|
||||
case DxbcOperandType::Temp:
|
||||
return this->getTempOperandPtr(operand);
|
||||
|
||||
case DxbcOperandType::Input:
|
||||
case DxbcOperandType::Output:
|
||||
return this->getInterfaceOperandPtr(operand);
|
||||
|
||||
default:
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::getOperandPtr: Unhandled operand type: ",
|
||||
operand.token().type()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCompiler::selectOperandComponents(
|
||||
const DxbcOperandToken& opToken,
|
||||
const DxbcValue& opValue,
|
||||
DxbcComponentMask dstMask) {
|
||||
// Four-component source operands can provide either a
|
||||
// swizzle to select multiple components, or a component
|
||||
// index that is used to select one single component.
|
||||
switch (opToken.selectionMode()) {
|
||||
case DxbcComponentSelectionMode::Swizzle:
|
||||
return m_gen->regSwizzle(opValue,
|
||||
opToken.componentSwizzle(), dstMask);
|
||||
|
||||
case DxbcComponentSelectionMode::Select1:
|
||||
return m_gen->regExtract(opValue,
|
||||
opToken.componentSelection());
|
||||
|
||||
default:
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::loadOperand: Invalid component selection mode: ",
|
||||
opToken.selectionMode()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCompiler::applyOperandModifiers(
|
||||
DxbcValue value,
|
||||
DxbcOperandModifiers modifiers) {
|
||||
if (modifiers.test(DxbcOperandModifier::Abs))
|
||||
value = m_gen->opAbs(value);
|
||||
|
||||
if (modifiers.test(DxbcOperandModifier::Neg))
|
||||
value = m_gen->opNeg(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCompiler::loadOperand(
|
||||
const DxbcOperand& operand,
|
||||
DxbcComponentMask dstMask,
|
||||
DxbcScalarType dstType) {
|
||||
const DxbcOperandToken token = operand.token();
|
||||
|
||||
DxbcValue result;
|
||||
|
||||
switch (token.type()) {
|
||||
case DxbcOperandType::Imm32: {
|
||||
if (token.numComponents() == 1) {
|
||||
result = m_gen->defConstScalar(operand.imm32(0));
|
||||
} else if (token.numComponents() == 4) {
|
||||
result = m_gen->defConstVector(
|
||||
operand.imm32(0), operand.imm32(1),
|
||||
operand.imm32(2), operand.imm32(3));
|
||||
} else {
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler::loadOperand [imm32]: Invalid number of components: ",
|
||||
token.numComponents()));
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
result = m_gen->regLoad(
|
||||
this->getOperandPtr(operand));
|
||||
};
|
||||
}
|
||||
|
||||
// Apply the source operand swizzle
|
||||
if (token.numComponents() == 4)
|
||||
result = this->selectOperandComponents(token, result, dstMask);
|
||||
|
||||
// Apply source operand modifiers, if any
|
||||
auto operandModifiers = operand.queryOperandExt(
|
||||
DxbcOperandExt::OperandModifier);
|
||||
|
||||
if (operandModifiers) {
|
||||
result = this->applyOperandModifiers(
|
||||
result, operandModifiers->data());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::storeOperand(
|
||||
const DxbcOperand& operand,
|
||||
DxbcValue value,
|
||||
DxbcComponentMask mask) {
|
||||
const DxbcPointer ptr = this->getOperandPtr(operand);
|
||||
|
||||
// Cast source value to destination register type.
|
||||
// TODO verify that this actually works as intended.
|
||||
DxbcValueType dstType;
|
||||
dstType.componentType = ptr.type.valueType.componentType;
|
||||
dstType.componentCount = mask.componentCount();
|
||||
value = m_gen->regCast(value, dstType);
|
||||
|
||||
m_gen->regStore(ptr, value, mask);
|
||||
}
|
||||
|
||||
}
|
@ -28,13 +28,50 @@ namespace dxvk {
|
||||
Rc<DxbcCodeGen> m_gen;
|
||||
|
||||
void dclGlobalFlags(
|
||||
const DxbcInstruction& ins);
|
||||
const DxbcInstruction& ins);
|
||||
|
||||
void dclInterfaceVar(
|
||||
const DxbcInstruction& ins);
|
||||
const DxbcInstruction& ins);
|
||||
|
||||
void dclTemps(
|
||||
const DxbcInstruction& ins);
|
||||
const DxbcInstruction& ins);
|
||||
|
||||
void opMov(
|
||||
const DxbcInstruction& ins);
|
||||
|
||||
void opRet(
|
||||
const DxbcInstruction& ins);
|
||||
|
||||
DxbcComponentMask getDstOperandMask(
|
||||
const DxbcOperand& operand);
|
||||
|
||||
DxbcPointer getTempOperandPtr(
|
||||
const DxbcOperand& operand);
|
||||
|
||||
DxbcPointer getInterfaceOperandPtr(
|
||||
const DxbcOperand& operand);
|
||||
|
||||
DxbcPointer getOperandPtr(
|
||||
const DxbcOperand& operand);
|
||||
|
||||
DxbcValue selectOperandComponents(
|
||||
const DxbcOperandToken& opToken,
|
||||
const DxbcValue& opValue,
|
||||
DxbcComponentMask dstMask);
|
||||
|
||||
DxbcValue applyOperandModifiers(
|
||||
DxbcValue value,
|
||||
DxbcOperandModifiers modifiers);
|
||||
|
||||
DxbcValue loadOperand(
|
||||
const DxbcOperand& operand,
|
||||
DxbcComponentMask dstMask,
|
||||
DxbcScalarType dstType);
|
||||
|
||||
void storeOperand(
|
||||
const DxbcOperand& operand,
|
||||
DxbcValue value,
|
||||
DxbcComponentMask mask);
|
||||
|
||||
};
|
||||
|
||||
|
@ -424,4 +424,12 @@ namespace dxvk {
|
||||
|
||||
using DxbcGlobalFlags = Flags<DxbcGlobalFlag>;
|
||||
|
||||
|
||||
enum class DxbcOperandModifier : uint32_t {
|
||||
Neg = 0,
|
||||
Abs = 1,
|
||||
};
|
||||
|
||||
using DxbcOperandModifiers = Flags<DxbcOperandModifier>;
|
||||
|
||||
}
|
@ -275,6 +275,14 @@ std::ostream& operator << (std::ostream& os, DxbcOperandType e) {
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandExt e) {
|
||||
switch (e) {
|
||||
ENUM_NAME(DxbcOperandExt::OperandModifier);
|
||||
ENUM_DEFAULT(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator << (std::ostream& os, DxbcComponentCount e) {
|
||||
switch (e) {
|
||||
ENUM_NAME(DxbcComponentCount::Component0);
|
||||
|
@ -8,6 +8,7 @@
|
||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcOpcode e);
|
||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcExtOpcode e);
|
||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandType e);
|
||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandExt e);
|
||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcComponentCount e);
|
||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcComponentSelectionMode e);
|
||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandIndexRepresentation e);
|
||||
|
@ -6,7 +6,6 @@
|
||||
namespace dxvk {
|
||||
|
||||
DxbcCodeGen::DxbcCodeGen() {
|
||||
m_module.enableCapability(spv::CapabilityShader);
|
||||
m_module.setMemoryModel(
|
||||
spv::AddressingModelLogical,
|
||||
spv::MemoryModelGLSL450);
|
||||
@ -25,31 +24,173 @@ namespace dxvk {
|
||||
if (n > oldSize) {
|
||||
m_rRegs.resize(n);
|
||||
|
||||
DxbcPointer reg;
|
||||
reg.type = DxbcPointerType(
|
||||
DxbcValueType(DxbcScalarType::Float32, 4),
|
||||
spv::StorageClassPrivate);
|
||||
|
||||
const uint32_t typeId = this->defPointerType(reg.type);
|
||||
|
||||
for (uint32_t i = oldSize; i < n; i++) {
|
||||
reg.valueId = m_module.newVar(typeId, spv::StorageClassPrivate);
|
||||
m_module.setDebugName(reg.valueId, str::format("r", i).c_str());
|
||||
m_rRegs.at(i) = reg;
|
||||
m_rRegs.at(i) = this->defVar(
|
||||
DxbcValueType(DxbcScalarType::Float32, 4),
|
||||
spv::StorageClassPrivate);
|
||||
m_module.setDebugName(m_rRegs.at(i).valueId,
|
||||
str::format("r", i).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCodeGen::defConstScalar(uint32_t v) {
|
||||
DxbcValue result;
|
||||
result.type = DxbcValueType(DxbcScalarType::Uint32, 1);
|
||||
result.valueId = m_module.constu32(v);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCodeGen::defConstVector(
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t z, uint32_t w) {
|
||||
std::array<uint32_t, 4> ids = {
|
||||
m_module.constu32(x),
|
||||
m_module.constu32(y),
|
||||
m_module.constu32(z),
|
||||
m_module.constu32(w) };
|
||||
|
||||
DxbcValue result;
|
||||
result.type = DxbcValueType(DxbcScalarType::Uint32, 4);
|
||||
result.valueId = m_module.constComposite(
|
||||
this->defValueType(result.type),
|
||||
ids.size(), ids.data());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void DxbcCodeGen::fnReturn() {
|
||||
// TODO implement control flow
|
||||
m_module.opReturn();
|
||||
m_module.functionEnd();
|
||||
}
|
||||
|
||||
|
||||
DxbcPointer DxbcCodeGen::ptrTempReg(uint32_t regId) {
|
||||
return m_rRegs.at(regId);
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCodeGen::vecStore(
|
||||
const DxbcValue& dst,
|
||||
const DxbcValue& src,
|
||||
DxbcComponentMask mask) {
|
||||
DxbcValue DxbcCodeGen::opAbs(const DxbcValue& src) {
|
||||
DxbcValue result;
|
||||
result.type = src.type;
|
||||
|
||||
switch (src.type.componentType) {
|
||||
case DxbcScalarType::Sint32:
|
||||
case DxbcScalarType::Sint64:
|
||||
result.valueId = m_module.opSAbs(
|
||||
this->defValueType(result.type),
|
||||
src.valueId);
|
||||
break;
|
||||
|
||||
case DxbcScalarType::Uint32:
|
||||
case DxbcScalarType::Uint64:
|
||||
result.valueId = src.valueId;
|
||||
break;
|
||||
|
||||
case DxbcScalarType::Float32:
|
||||
case DxbcScalarType::Float64:
|
||||
result.valueId = m_module.opFAbs(
|
||||
this->defValueType(result.type),
|
||||
src.valueId);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DxbcValue DxbcCodeGen::opNeg(const DxbcValue& src) {
|
||||
DxbcValue result;
|
||||
result.type = src.type;
|
||||
|
||||
switch (src.type.componentType) {
|
||||
case DxbcScalarType::Sint32:
|
||||
case DxbcScalarType::Sint64:
|
||||
case DxbcScalarType::Uint32:
|
||||
case DxbcScalarType::Uint64:
|
||||
result.valueId = m_module.opSNegate(
|
||||
this->defValueType(result.type),
|
||||
src.valueId);
|
||||
break;
|
||||
|
||||
case DxbcScalarType::Float32:
|
||||
case DxbcScalarType::Float64:
|
||||
result.valueId = m_module.opFNegate(
|
||||
this->defValueType(result.type),
|
||||
src.valueId);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCodeGen::regCast(
|
||||
const DxbcValue& src,
|
||||
const DxbcValueType& type) {
|
||||
if (src.type.componentType == type.componentType)
|
||||
return src;
|
||||
|
||||
DxbcValue result;
|
||||
result.type = type;
|
||||
result.valueId = m_module.opBitcast(
|
||||
this->defValueType(result.type),
|
||||
src.valueId);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCodeGen::regExtract(
|
||||
const DxbcValue& src,
|
||||
DxbcComponentMask mask) {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCodeGen::regSwizzle(
|
||||
const DxbcValue& src,
|
||||
const DxbcComponentSwizzle& swizzle,
|
||||
DxbcComponentMask mask) {
|
||||
std::array<uint32_t, 4> indices;
|
||||
|
||||
uint32_t dstIndex = 0;
|
||||
for (uint32_t i = 0; i < src.type.componentCount; i++) {
|
||||
if (mask.test(i))
|
||||
indices[dstIndex++] = swizzle[i];
|
||||
}
|
||||
|
||||
bool isIdentitySwizzle = dstIndex == src.type.componentCount;
|
||||
|
||||
for (uint32_t i = 0; i < dstIndex && isIdentitySwizzle; i++)
|
||||
isIdentitySwizzle &= indices[i] == i;
|
||||
|
||||
if (isIdentitySwizzle)
|
||||
return src;
|
||||
|
||||
DxbcValue result;
|
||||
result.type = DxbcValueType(src.type.componentType, dstIndex);
|
||||
|
||||
if (dstIndex == 1) {
|
||||
result.valueId = m_module.opCompositeExtract(
|
||||
this->defValueType(result.type),
|
||||
src.valueId, 1, indices.data());
|
||||
} else {
|
||||
result.valueId = m_module.opVectorShuffle(
|
||||
this->defValueType(result.type),
|
||||
src.valueId, src.valueId,
|
||||
dstIndex, indices.data());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCodeGen::regInsert(
|
||||
const DxbcValue& dst,
|
||||
const DxbcValue& src,
|
||||
DxbcComponentMask mask) {
|
||||
DxbcValue result;
|
||||
result.type = dst.type;
|
||||
|
||||
@ -100,15 +241,15 @@ namespace dxvk {
|
||||
|
||||
|
||||
void DxbcCodeGen::regStore(
|
||||
const DxbcPointer& ptr,
|
||||
const DxbcValue& val,
|
||||
DxbcComponentMask mask) {
|
||||
const DxbcPointer& ptr,
|
||||
const DxbcValue& val,
|
||||
DxbcComponentMask mask) {
|
||||
if (ptr.type.valueType.componentCount != val.type.componentCount) {
|
||||
// In case we write to only a part of the destination
|
||||
// register, we need to load the previous value first
|
||||
// and then update the given components.
|
||||
DxbcValue tmp = this->regLoad(ptr);
|
||||
tmp = this->vecStore(tmp, val, mask);
|
||||
tmp = this->regInsert(tmp, val, mask);
|
||||
|
||||
m_module.opStore(ptr.valueId, tmp.valueId);
|
||||
} else {
|
||||
@ -195,4 +336,16 @@ namespace dxvk {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
|
||||
DxbcPointer DxbcCodeGen::defVar(
|
||||
const DxbcValueType& type,
|
||||
spv::StorageClass storageClass) {
|
||||
DxbcPointer result;
|
||||
result.type = DxbcPointerType(type, storageClass);
|
||||
result.valueId = m_module.newVar(
|
||||
this->defPointerType(result.type),
|
||||
storageClass);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -37,6 +37,12 @@ namespace dxvk {
|
||||
|
||||
virtual ~DxbcCodeGen();
|
||||
|
||||
/**
|
||||
* \brief Declares temporary registers
|
||||
* \param [in] n Number of temp registers
|
||||
*/
|
||||
void dclTemps(uint32_t n);
|
||||
|
||||
/**
|
||||
* \brief Declares an interface variable
|
||||
*
|
||||
@ -54,10 +60,36 @@ namespace dxvk {
|
||||
DxbcSystemValue sv) = 0;
|
||||
|
||||
/**
|
||||
* \brief Declares temporary registers
|
||||
* \param [in] n Number of temp registers
|
||||
* \brief Defines 32-bit constant
|
||||
*
|
||||
* The constant will be declared as a 32-bit
|
||||
* unsigned integer. Cast the resulting value
|
||||
* to the required type.
|
||||
* \param [in] v Constant value
|
||||
* \returns The constant value ID
|
||||
*/
|
||||
void dclTemps(uint32_t n);
|
||||
DxbcValue defConstScalar(uint32_t v);
|
||||
|
||||
/**
|
||||
* \brief Defines 32-bit constant vector
|
||||
*
|
||||
* Defines a four-component vector of 32-bit
|
||||
* unsigned integer values. Cast the resulting
|
||||
* value to the required type as needed.
|
||||
* \param [in] x First vector component
|
||||
* \param [in] y Second vector component
|
||||
* \param [in] z Third vector component
|
||||
* \param [in] w Fourth vector component
|
||||
* \returns The constant value ID
|
||||
*/
|
||||
DxbcValue defConstVector(
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t z, uint32_t w);
|
||||
|
||||
/**
|
||||
* \brief Returns from function
|
||||
*/
|
||||
void fnReturn();
|
||||
|
||||
/**
|
||||
* \brief Retrieves temporary register pointer
|
||||
@ -69,42 +101,6 @@ namespace dxvk {
|
||||
DxbcPointer ptrTempReg(
|
||||
uint32_t regId);
|
||||
|
||||
/**
|
||||
* \brief Writes to parts of a vector register
|
||||
*
|
||||
* Note that the source value must not have the
|
||||
* same number of components as the write mask.
|
||||
* \param [in] dst Destination value ID
|
||||
* \param [in] src Source value ID
|
||||
* \param [in] mask Write mask
|
||||
* \returns New destination value ID
|
||||
*/
|
||||
DxbcValue vecStore(
|
||||
const DxbcValue& dst,
|
||||
const DxbcValue& src,
|
||||
DxbcComponentMask mask);
|
||||
|
||||
/**
|
||||
* \brief Loads register
|
||||
*
|
||||
* \param [in] ptr Register pointer
|
||||
* \returns The register value ID
|
||||
*/
|
||||
DxbcValue regLoad(
|
||||
const DxbcPointer& ptr);
|
||||
|
||||
/**
|
||||
* \brief Stores register
|
||||
*
|
||||
* \param [in] ptr Register pointer
|
||||
* \param [in] val Value ID to store
|
||||
* \param [in] mask Write mask
|
||||
*/
|
||||
void regStore(
|
||||
const DxbcPointer& ptr,
|
||||
const DxbcValue& val,
|
||||
DxbcComponentMask mask);
|
||||
|
||||
/**
|
||||
* \brief Pointer to an interface variable
|
||||
*
|
||||
@ -113,9 +109,9 @@ namespace dxvk {
|
||||
* \param [in] regId Register index
|
||||
* \returns Register pointer
|
||||
*/
|
||||
virtual void ptrInterfaceVar(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId) = 0;
|
||||
virtual DxbcPointer ptrInterfaceVar(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId) = 0;
|
||||
|
||||
/**
|
||||
* \brief Pointer to an interface variable
|
||||
@ -128,10 +124,93 @@ namespace dxvk {
|
||||
* \param [in] index Array index
|
||||
* \returns Register pointer
|
||||
*/
|
||||
virtual void ptrInterfaceVarIndexed(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId,
|
||||
const DxbcValue& index) = 0;
|
||||
virtual DxbcPointer ptrInterfaceVarIndexed(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId,
|
||||
const DxbcValue& index) = 0;
|
||||
|
||||
DxbcValue opAbs(
|
||||
const DxbcValue& src);
|
||||
|
||||
DxbcValue opNeg(
|
||||
const DxbcValue& src);
|
||||
|
||||
/**
|
||||
* \brief Casts register value to another type
|
||||
*
|
||||
* Type cast that does not change the bit pattern
|
||||
* of the value. This is required as DXBC values
|
||||
* are not statically typed, but SPIR-V is.
|
||||
* \param [in] src Source value
|
||||
* \param [in] type Destination type
|
||||
* \returns Resulting register value
|
||||
*/
|
||||
DxbcValue regCast(
|
||||
const DxbcValue& src,
|
||||
const DxbcValueType& type);
|
||||
|
||||
/**
|
||||
* \brief Extracts vector components
|
||||
*
|
||||
* Extracts the given set of components.
|
||||
* \param [in] src Source vector
|
||||
* \param [in] mask Component mask
|
||||
* \returns Resulting register value
|
||||
*/
|
||||
DxbcValue regExtract(
|
||||
const DxbcValue& src,
|
||||
DxbcComponentMask mask);
|
||||
|
||||
/**
|
||||
* \brief Swizzles a vector register
|
||||
*
|
||||
* Swizzles the vector and extracts
|
||||
* the given set of vector components.
|
||||
* \param [in] src Source vector to swizzle
|
||||
* \param [in] swizzle The component swizzle
|
||||
* \param [in] mask Components to extract
|
||||
* \returns Resulting register value
|
||||
*/
|
||||
DxbcValue regSwizzle(
|
||||
const DxbcValue& src,
|
||||
const DxbcComponentSwizzle& swizzle,
|
||||
DxbcComponentMask mask);
|
||||
|
||||
/**
|
||||
* \brief Writes to parts of a vector register
|
||||
*
|
||||
* Note that the source value must have the same
|
||||
* number of components as the write mask.
|
||||
* \param [in] dst Destination value ID
|
||||
* \param [in] src Source value ID
|
||||
* \param [in] mask Write mask
|
||||
* \returns New destination value ID
|
||||
*/
|
||||
DxbcValue regInsert(
|
||||
const DxbcValue& dst,
|
||||
const DxbcValue& src,
|
||||
DxbcComponentMask mask);
|
||||
|
||||
/**
|
||||
* \brief Loads register
|
||||
*
|
||||
* \param [in] ptr Register pointer
|
||||
* \returns The register value ID
|
||||
*/
|
||||
DxbcValue regLoad(
|
||||
const DxbcPointer& ptr);
|
||||
|
||||
/**
|
||||
* \brief Stores register
|
||||
*
|
||||
* \param [in] ptr Register pointer
|
||||
* \param [in] val Value ID to store
|
||||
* \param [in] mask Write mask
|
||||
*/
|
||||
void regStore(
|
||||
const DxbcPointer& ptr,
|
||||
const DxbcValue& val,
|
||||
DxbcComponentMask mask);
|
||||
|
||||
/**
|
||||
* \brief Finalizes shader
|
||||
@ -177,6 +256,10 @@ namespace dxvk {
|
||||
|
||||
uint32_t defPerVertexBlock();
|
||||
|
||||
DxbcPointer defVar(
|
||||
const DxbcValueType& type,
|
||||
spv::StorageClass storageClass);
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -3,9 +3,25 @@
|
||||
namespace dxvk {
|
||||
|
||||
DxbcVsCodeGen::DxbcVsCodeGen() {
|
||||
m_module.enableCapability(spv::CapabilityShader);
|
||||
m_module.enableCapability(spv::CapabilityCullDistance);
|
||||
m_module.enableCapability(spv::CapabilityClipDistance);
|
||||
|
||||
m_function = m_module.allocateId();
|
||||
m_module.setDebugName(m_function, "vs_main");
|
||||
|
||||
m_module.functionBegin(
|
||||
m_module.defVoidType(),
|
||||
m_function,
|
||||
m_module.defFunctionType(
|
||||
m_module.defVoidType(), 0, nullptr),
|
||||
spv::FunctionControlMaskNone);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
|
||||
m_outPerVertex = m_module.newVar(
|
||||
m_module.defPointerType(this->defPerVertexBlock(), spv::StorageClassOutput),
|
||||
spv::StorageClassOutput);
|
||||
m_entryPointInterfaces.push_back(m_outPerVertex);
|
||||
m_module.setDebugName(m_outPerVertex, "vs_out");
|
||||
}
|
||||
|
||||
@ -21,18 +37,79 @@ namespace dxvk {
|
||||
uint32_t regDim,
|
||||
DxbcComponentMask regMask,
|
||||
DxbcSystemValue sv) {
|
||||
|
||||
switch (regType) {
|
||||
case DxbcOperandType::Input: {
|
||||
if (sv == DxbcSystemValue::None) {
|
||||
if (m_vRegs.at(regId).valueId == 0) {
|
||||
m_vRegs.at(regId) = this->defVar(
|
||||
DxbcValueType(DxbcScalarType::Float32, 4),
|
||||
spv::StorageClassInput);
|
||||
m_module.setDebugName(m_vRegs.at(regId).valueId,
|
||||
str::format("v", regId).c_str());
|
||||
m_module.decorateLocation(
|
||||
m_vRegs.at(regId).valueId, regId);
|
||||
m_entryPointInterfaces.push_back(
|
||||
m_vRegs.at(regId).valueId);
|
||||
}
|
||||
} else {
|
||||
if (m_vRegsSv.at(regId).valueId == 0) {
|
||||
m_vRegsSv.at(regId) = this->defVar(
|
||||
DxbcValueType(DxbcScalarType::Float32, 4),
|
||||
spv::StorageClassPrivate);
|
||||
m_module.setDebugName(m_vRegsSv.at(regId).valueId,
|
||||
str::format("sv", regId).c_str());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case DxbcOperandType::Output: {
|
||||
if (m_oRegs.at(regId).valueId == 0) {
|
||||
m_oRegs.at(regId) = this->defVar(
|
||||
DxbcValueType(DxbcScalarType::Float32, 4),
|
||||
spv::StorageClassOutput);
|
||||
m_module.setDebugName(m_oRegs.at(regId).valueId,
|
||||
str::format("o", regId).c_str());
|
||||
m_module.decorateLocation(
|
||||
m_oRegs.at(regId).valueId, regId);
|
||||
m_entryPointInterfaces.push_back(
|
||||
m_oRegs.at(regId).valueId);
|
||||
}
|
||||
|
||||
if (sv != DxbcSystemValue::None) {
|
||||
m_svOutputs.push_back(DxbcSvMapping {
|
||||
regId, regMask, sv });
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
throw DxvkError(str::format(
|
||||
"DxbcVsCodeGen::dclInterfaceVar: Unhandled operand type: ",
|
||||
regType));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxbcVsCodeGen::ptrInterfaceVar(
|
||||
DxbcPointer DxbcVsCodeGen::ptrInterfaceVar(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId) {
|
||||
|
||||
switch (regType) {
|
||||
case DxbcOperandType::Input:
|
||||
return m_vRegsSv.at(regId).valueId != 0
|
||||
? m_vRegsSv.at(regId)
|
||||
: m_vRegs .at(regId);
|
||||
|
||||
case DxbcOperandType::Output:
|
||||
return m_oRegs.at(regId);
|
||||
|
||||
default:
|
||||
throw DxvkError(str::format(
|
||||
"DxbcVsCodeGen::ptrInterfaceVar: Unhandled operand type: ",
|
||||
regType));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxbcVsCodeGen::ptrInterfaceVarIndexed(
|
||||
DxbcPointer DxbcVsCodeGen::ptrInterfaceVarIndexed(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId,
|
||||
const DxbcValue& index) {
|
||||
@ -43,6 +120,23 @@ namespace dxvk {
|
||||
|
||||
|
||||
Rc<DxvkShader> DxbcVsCodeGen::finalize() {
|
||||
m_module.functionBegin(
|
||||
m_module.defVoidType(),
|
||||
m_entryPointId,
|
||||
m_module.defFunctionType(
|
||||
m_module.defVoidType(), 0, nullptr),
|
||||
spv::FunctionControlMaskNone);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
|
||||
this->prepareSvInputs();
|
||||
m_module.opFunctionCall(
|
||||
m_module.defVoidType(),
|
||||
m_function, 0, nullptr);
|
||||
this->prepareSvOutputs();
|
||||
|
||||
m_module.opReturn();
|
||||
m_module.functionEnd();
|
||||
|
||||
m_module.addEntryPoint(m_entryPointId,
|
||||
spv::ExecutionModelVertex, "main",
|
||||
m_entryPointInterfaces.size(),
|
||||
@ -53,4 +147,49 @@ namespace dxvk {
|
||||
m_module.compile(), 0, nullptr);
|
||||
}
|
||||
|
||||
|
||||
void DxbcVsCodeGen::prepareSvInputs() {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
|
||||
void DxbcVsCodeGen::prepareSvOutputs() {
|
||||
for (const auto& sv : m_svOutputs) {
|
||||
DxbcValue val = this->regLoad(m_oRegs.at(sv.regId));
|
||||
// val = this->regExtract(val, sv.regMask);
|
||||
|
||||
DxbcPointer dst;
|
||||
|
||||
switch (sv.sv) {
|
||||
case DxbcSystemValue::Position:
|
||||
dst = this->ptrBuiltInPosition();
|
||||
break;
|
||||
|
||||
default:
|
||||
Logger::err(str::format(
|
||||
"DxbcVsCodeGen::prepareSvOutputs: Unsupported system value: ",
|
||||
sv.sv));
|
||||
}
|
||||
|
||||
if (dst.valueId != 0) {
|
||||
// val = this->regCast(val, dst.type.valueType);
|
||||
this->regStore(dst, val, DxbcComponentMask());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxbcPointer DxbcVsCodeGen::ptrBuiltInPosition() {
|
||||
const uint32_t memberId = m_module.constu32(PerVertex_Position);
|
||||
|
||||
DxbcPointer result;
|
||||
result.type = DxbcPointerType(
|
||||
DxbcValueType(DxbcScalarType::Float32, 4),
|
||||
spv::StorageClassOutput);
|
||||
result.valueId = m_module.opAccessChain(
|
||||
this->defPointerType(result.type),
|
||||
m_outPerVertex, 1, &memberId);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -21,11 +21,11 @@ namespace dxvk {
|
||||
DxbcComponentMask regMask,
|
||||
DxbcSystemValue sv);
|
||||
|
||||
void ptrInterfaceVar(
|
||||
DxbcPointer ptrInterfaceVar(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId);
|
||||
|
||||
void ptrInterfaceVarIndexed(
|
||||
DxbcPointer ptrInterfaceVarIndexed(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId,
|
||||
const DxbcValue& index);
|
||||
@ -34,14 +34,21 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_function = 0;
|
||||
uint32_t m_outPerVertex = 0;
|
||||
|
||||
std::array<DxbcPointer, 32> m_vRegs;
|
||||
std::array<DxbcPointer, 32> m_vRegsSv;
|
||||
std::array<DxbcPointer, 32> m_oRegs;
|
||||
|
||||
std::vector<DxbcSvMapping> m_svInputs;
|
||||
std::vector<DxbcSvMapping> m_svOutputs;
|
||||
|
||||
void prepareSvInputs();
|
||||
void prepareSvOutputs();
|
||||
|
||||
DxbcPointer ptrBuiltInPosition();
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <spirv/spirv.hpp>
|
||||
#include <spirv/GLSL.std.450.hpp>
|
||||
|
||||
#include "spirv_include.h"
|
||||
|
||||
|
@ -2,14 +2,21 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
SpirvModule:: SpirvModule() { }
|
||||
SpirvModule::~SpirvModule() { }
|
||||
SpirvModule:: SpirvModule() {
|
||||
this->instImportGlsl450();
|
||||
}
|
||||
|
||||
|
||||
SpirvModule::~SpirvModule() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
SpirvCodeBuffer SpirvModule::compile() const {
|
||||
SpirvCodeBuffer result;
|
||||
result.putHeader(m_id);
|
||||
result.append(m_capabilities);
|
||||
result.append(m_instExt);
|
||||
result.append(m_memoryModel);
|
||||
result.append(m_entryPoints);
|
||||
result.append(m_execModeInfo);
|
||||
@ -413,6 +420,24 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opAccessChain(
|
||||
uint32_t resultType,
|
||||
uint32_t composite,
|
||||
uint32_t indexCount,
|
||||
const uint32_t* indexArray) {
|
||||
uint32_t resultId = this->allocateId();
|
||||
|
||||
m_code.putIns (spv::OpAccessChain, 4 + indexCount);
|
||||
m_code.putWord(resultType);
|
||||
m_code.putWord(resultId);
|
||||
m_code.putWord(composite);
|
||||
|
||||
for (uint32_t i = 0; i < indexCount; i++)
|
||||
m_code.putInt32(indexArray[i]);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opBitcast(
|
||||
uint32_t resultType,
|
||||
uint32_t operand) {
|
||||
@ -484,6 +509,62 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opSNegate(
|
||||
uint32_t resultType,
|
||||
uint32_t operand) {
|
||||
uint32_t resultId = this->allocateId();
|
||||
|
||||
m_code.putIns (spv::OpSNegate, 4);
|
||||
m_code.putWord(resultType);
|
||||
m_code.putWord(resultId);
|
||||
m_code.putWord(operand);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opFNegate(
|
||||
uint32_t resultType,
|
||||
uint32_t operand) {
|
||||
uint32_t resultId = this->allocateId();
|
||||
|
||||
m_code.putIns (spv::OpFNegate, 4);
|
||||
m_code.putWord(resultType);
|
||||
m_code.putWord(resultId);
|
||||
m_code.putWord(operand);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opSAbs(
|
||||
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::GLSLstd450SAbs);
|
||||
m_code.putWord(operand);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opFAbs(
|
||||
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::GLSLstd450FAbs);
|
||||
m_code.putWord(operand);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opFunctionCall(
|
||||
uint32_t resultType,
|
||||
uint32_t functionId,
|
||||
@ -562,4 +643,14 @@ namespace dxvk {
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
void SpirvModule::instImportGlsl450() {
|
||||
m_instExtGlsl450 = this->allocateId();
|
||||
const char* name = "GLSL.std.450";
|
||||
|
||||
m_instExt.putIns (spv::OpExtInstImport, 2 + m_instExt.strLen(name));
|
||||
m_instExt.putWord(m_instExtGlsl450);
|
||||
m_instExt.putStr (name);
|
||||
}
|
||||
|
||||
}
|
@ -155,6 +155,12 @@ namespace dxvk {
|
||||
|
||||
void functionEnd();
|
||||
|
||||
uint32_t opAccessChain(
|
||||
uint32_t resultType,
|
||||
uint32_t composite,
|
||||
uint32_t indexCount,
|
||||
const uint32_t* indexArray);
|
||||
|
||||
uint32_t opBitcast(
|
||||
uint32_t resultType,
|
||||
uint32_t operand);
|
||||
@ -179,6 +185,22 @@ namespace dxvk {
|
||||
uint32_t indexCount,
|
||||
const uint32_t* indexArray);
|
||||
|
||||
uint32_t opSNegate(
|
||||
uint32_t resultType,
|
||||
uint32_t operand);
|
||||
|
||||
uint32_t opFNegate(
|
||||
uint32_t resultType,
|
||||
uint32_t operand);
|
||||
|
||||
uint32_t opSAbs(
|
||||
uint32_t resultType,
|
||||
uint32_t operand);
|
||||
|
||||
uint32_t opFAbs(
|
||||
uint32_t resultType,
|
||||
uint32_t operand);
|
||||
|
||||
uint32_t opFunctionCall(
|
||||
uint32_t resultType,
|
||||
uint32_t functionId,
|
||||
@ -200,9 +222,11 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_id = 1;
|
||||
uint32_t m_id = 1;
|
||||
uint32_t m_instExtGlsl450 = 0;
|
||||
|
||||
SpirvCodeBuffer m_capabilities;
|
||||
SpirvCodeBuffer m_instExt;
|
||||
SpirvCodeBuffer m_memoryModel;
|
||||
SpirvCodeBuffer m_entryPoints;
|
||||
SpirvCodeBuffer m_execModeInfo;
|
||||
@ -217,6 +241,8 @@ namespace dxvk {
|
||||
uint32_t argCount,
|
||||
const uint32_t* argIds);
|
||||
|
||||
void instImportGlsl450();
|
||||
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user