mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +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:
|
case DxbcOpcode::DclTemps:
|
||||||
return this->dclTemps(ins);
|
return this->dclTemps(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::Mov:
|
||||||
|
return this->opMov(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::Ret:
|
||||||
|
return this->opRet(ins);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Logger::err(str::format(
|
Logger::err(str::format(
|
||||||
"DxbcCompiler::processInstruction: Unhandled opcode: ",
|
"DxbcCompiler::processInstruction: Unhandled opcode: ",
|
||||||
@ -52,7 +58,49 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::dclInterfaceVar(const DxbcInstruction& ins) {
|
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));
|
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;
|
Rc<DxbcCodeGen> m_gen;
|
||||||
|
|
||||||
void dclGlobalFlags(
|
void dclGlobalFlags(
|
||||||
const DxbcInstruction& ins);
|
const DxbcInstruction& ins);
|
||||||
|
|
||||||
void dclInterfaceVar(
|
void dclInterfaceVar(
|
||||||
const DxbcInstruction& ins);
|
const DxbcInstruction& ins);
|
||||||
|
|
||||||
void dclTemps(
|
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>;
|
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) {
|
std::ostream& operator << (std::ostream& os, DxbcComponentCount e) {
|
||||||
switch (e) {
|
switch (e) {
|
||||||
ENUM_NAME(DxbcComponentCount::Component0);
|
ENUM_NAME(DxbcComponentCount::Component0);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcOpcode e);
|
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::DxbcExtOpcode e);
|
||||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandType 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::DxbcComponentCount e);
|
||||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcComponentSelectionMode e);
|
std::ostream& operator << (std::ostream& os, dxvk::DxbcComponentSelectionMode e);
|
||||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandIndexRepresentation e);
|
std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandIndexRepresentation e);
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxbcCodeGen::DxbcCodeGen() {
|
DxbcCodeGen::DxbcCodeGen() {
|
||||||
m_module.enableCapability(spv::CapabilityShader);
|
|
||||||
m_module.setMemoryModel(
|
m_module.setMemoryModel(
|
||||||
spv::AddressingModelLogical,
|
spv::AddressingModelLogical,
|
||||||
spv::MemoryModelGLSL450);
|
spv::MemoryModelGLSL450);
|
||||||
@ -25,31 +24,173 @@ namespace dxvk {
|
|||||||
if (n > oldSize) {
|
if (n > oldSize) {
|
||||||
m_rRegs.resize(n);
|
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++) {
|
for (uint32_t i = oldSize; i < n; i++) {
|
||||||
reg.valueId = m_module.newVar(typeId, spv::StorageClassPrivate);
|
m_rRegs.at(i) = this->defVar(
|
||||||
m_module.setDebugName(reg.valueId, str::format("r", i).c_str());
|
DxbcValueType(DxbcScalarType::Float32, 4),
|
||||||
m_rRegs.at(i) = reg;
|
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) {
|
DxbcPointer DxbcCodeGen::ptrTempReg(uint32_t regId) {
|
||||||
return m_rRegs.at(regId);
|
return m_rRegs.at(regId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DxbcValue DxbcCodeGen::vecStore(
|
DxbcValue DxbcCodeGen::opAbs(const DxbcValue& src) {
|
||||||
const DxbcValue& dst,
|
DxbcValue result;
|
||||||
const DxbcValue& src,
|
result.type = src.type;
|
||||||
DxbcComponentMask mask) {
|
|
||||||
|
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;
|
DxbcValue result;
|
||||||
result.type = dst.type;
|
result.type = dst.type;
|
||||||
|
|
||||||
@ -100,15 +241,15 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxbcCodeGen::regStore(
|
void DxbcCodeGen::regStore(
|
||||||
const DxbcPointer& ptr,
|
const DxbcPointer& ptr,
|
||||||
const DxbcValue& val,
|
const DxbcValue& val,
|
||||||
DxbcComponentMask mask) {
|
DxbcComponentMask mask) {
|
||||||
if (ptr.type.valueType.componentCount != val.type.componentCount) {
|
if (ptr.type.valueType.componentCount != val.type.componentCount) {
|
||||||
// In case we write to only a part of the destination
|
// In case we write to only a part of the destination
|
||||||
// register, we need to load the previous value first
|
// register, we need to load the previous value first
|
||||||
// and then update the given components.
|
// and then update the given components.
|
||||||
DxbcValue tmp = this->regLoad(ptr);
|
DxbcValue tmp = this->regLoad(ptr);
|
||||||
tmp = this->vecStore(tmp, val, mask);
|
tmp = this->regInsert(tmp, val, mask);
|
||||||
|
|
||||||
m_module.opStore(ptr.valueId, tmp.valueId);
|
m_module.opStore(ptr.valueId, tmp.valueId);
|
||||||
} else {
|
} else {
|
||||||
@ -195,4 +336,16 @@ namespace dxvk {
|
|||||||
return typeId;
|
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();
|
virtual ~DxbcCodeGen();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Declares temporary registers
|
||||||
|
* \param [in] n Number of temp registers
|
||||||
|
*/
|
||||||
|
void dclTemps(uint32_t n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Declares an interface variable
|
* \brief Declares an interface variable
|
||||||
*
|
*
|
||||||
@ -54,10 +60,36 @@ namespace dxvk {
|
|||||||
DxbcSystemValue sv) = 0;
|
DxbcSystemValue sv) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Declares temporary registers
|
* \brief Defines 32-bit constant
|
||||||
* \param [in] n Number of temp registers
|
*
|
||||||
|
* 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
|
* \brief Retrieves temporary register pointer
|
||||||
@ -69,42 +101,6 @@ namespace dxvk {
|
|||||||
DxbcPointer ptrTempReg(
|
DxbcPointer ptrTempReg(
|
||||||
uint32_t regId);
|
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
|
* \brief Pointer to an interface variable
|
||||||
*
|
*
|
||||||
@ -113,9 +109,9 @@ namespace dxvk {
|
|||||||
* \param [in] regId Register index
|
* \param [in] regId Register index
|
||||||
* \returns Register pointer
|
* \returns Register pointer
|
||||||
*/
|
*/
|
||||||
virtual void ptrInterfaceVar(
|
virtual DxbcPointer ptrInterfaceVar(
|
||||||
DxbcOperandType regType,
|
DxbcOperandType regType,
|
||||||
uint32_t regId) = 0;
|
uint32_t regId) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Pointer to an interface variable
|
* \brief Pointer to an interface variable
|
||||||
@ -128,10 +124,93 @@ namespace dxvk {
|
|||||||
* \param [in] index Array index
|
* \param [in] index Array index
|
||||||
* \returns Register pointer
|
* \returns Register pointer
|
||||||
*/
|
*/
|
||||||
virtual void ptrInterfaceVarIndexed(
|
virtual DxbcPointer ptrInterfaceVarIndexed(
|
||||||
DxbcOperandType regType,
|
DxbcOperandType regType,
|
||||||
uint32_t regId,
|
uint32_t regId,
|
||||||
const DxbcValue& index) = 0;
|
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
|
* \brief Finalizes shader
|
||||||
@ -177,6 +256,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
uint32_t defPerVertexBlock();
|
uint32_t defPerVertexBlock();
|
||||||
|
|
||||||
|
DxbcPointer defVar(
|
||||||
|
const DxbcValueType& type,
|
||||||
|
spv::StorageClass storageClass);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -3,9 +3,25 @@
|
|||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxbcVsCodeGen::DxbcVsCodeGen() {
|
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_outPerVertex = m_module.newVar(
|
||||||
m_module.defPointerType(this->defPerVertexBlock(), spv::StorageClassOutput),
|
m_module.defPointerType(this->defPerVertexBlock(), spv::StorageClassOutput),
|
||||||
spv::StorageClassOutput);
|
spv::StorageClassOutput);
|
||||||
|
m_entryPointInterfaces.push_back(m_outPerVertex);
|
||||||
m_module.setDebugName(m_outPerVertex, "vs_out");
|
m_module.setDebugName(m_outPerVertex, "vs_out");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,18 +37,79 @@ namespace dxvk {
|
|||||||
uint32_t regDim,
|
uint32_t regDim,
|
||||||
DxbcComponentMask regMask,
|
DxbcComponentMask regMask,
|
||||||
DxbcSystemValue sv) {
|
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,
|
DxbcOperandType regType,
|
||||||
uint32_t regId) {
|
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,
|
DxbcOperandType regType,
|
||||||
uint32_t regId,
|
uint32_t regId,
|
||||||
const DxbcValue& index) {
|
const DxbcValue& index) {
|
||||||
@ -43,6 +120,23 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
Rc<DxvkShader> DxbcVsCodeGen::finalize() {
|
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,
|
m_module.addEntryPoint(m_entryPointId,
|
||||||
spv::ExecutionModelVertex, "main",
|
spv::ExecutionModelVertex, "main",
|
||||||
m_entryPointInterfaces.size(),
|
m_entryPointInterfaces.size(),
|
||||||
@ -53,4 +147,49 @@ namespace dxvk {
|
|||||||
m_module.compile(), 0, nullptr);
|
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,
|
DxbcComponentMask regMask,
|
||||||
DxbcSystemValue sv);
|
DxbcSystemValue sv);
|
||||||
|
|
||||||
void ptrInterfaceVar(
|
DxbcPointer ptrInterfaceVar(
|
||||||
DxbcOperandType regType,
|
DxbcOperandType regType,
|
||||||
uint32_t regId);
|
uint32_t regId);
|
||||||
|
|
||||||
void ptrInterfaceVarIndexed(
|
DxbcPointer ptrInterfaceVarIndexed(
|
||||||
DxbcOperandType regType,
|
DxbcOperandType regType,
|
||||||
uint32_t regId,
|
uint32_t regId,
|
||||||
const DxbcValue& index);
|
const DxbcValue& index);
|
||||||
@ -34,14 +34,21 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
uint32_t m_function = 0;
|
||||||
uint32_t m_outPerVertex = 0;
|
uint32_t m_outPerVertex = 0;
|
||||||
|
|
||||||
std::array<DxbcPointer, 32> m_vRegs;
|
std::array<DxbcPointer, 32> m_vRegs;
|
||||||
|
std::array<DxbcPointer, 32> m_vRegsSv;
|
||||||
std::array<DxbcPointer, 32> m_oRegs;
|
std::array<DxbcPointer, 32> m_oRegs;
|
||||||
|
|
||||||
std::vector<DxbcSvMapping> m_svInputs;
|
std::vector<DxbcSvMapping> m_svInputs;
|
||||||
std::vector<DxbcSvMapping> m_svOutputs;
|
std::vector<DxbcSvMapping> m_svOutputs;
|
||||||
|
|
||||||
|
void prepareSvInputs();
|
||||||
|
void prepareSvOutputs();
|
||||||
|
|
||||||
|
DxbcPointer ptrBuiltInPosition();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <spirv/spirv.hpp>
|
#include <spirv/spirv.hpp>
|
||||||
|
#include <spirv/GLSL.std.450.hpp>
|
||||||
|
|
||||||
#include "spirv_include.h"
|
#include "spirv_include.h"
|
||||||
|
|
||||||
|
@ -2,14 +2,21 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
SpirvModule:: SpirvModule() { }
|
SpirvModule:: SpirvModule() {
|
||||||
SpirvModule::~SpirvModule() { }
|
this->instImportGlsl450();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SpirvModule::~SpirvModule() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SpirvCodeBuffer SpirvModule::compile() const {
|
SpirvCodeBuffer SpirvModule::compile() const {
|
||||||
SpirvCodeBuffer result;
|
SpirvCodeBuffer result;
|
||||||
result.putHeader(m_id);
|
result.putHeader(m_id);
|
||||||
result.append(m_capabilities);
|
result.append(m_capabilities);
|
||||||
|
result.append(m_instExt);
|
||||||
result.append(m_memoryModel);
|
result.append(m_memoryModel);
|
||||||
result.append(m_entryPoints);
|
result.append(m_entryPoints);
|
||||||
result.append(m_execModeInfo);
|
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 SpirvModule::opBitcast(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t operand) {
|
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 SpirvModule::opFunctionCall(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t functionId,
|
uint32_t functionId,
|
||||||
@ -562,4 +643,14 @@ namespace dxvk {
|
|||||||
return resultId;
|
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();
|
void functionEnd();
|
||||||
|
|
||||||
|
uint32_t opAccessChain(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t composite,
|
||||||
|
uint32_t indexCount,
|
||||||
|
const uint32_t* indexArray);
|
||||||
|
|
||||||
uint32_t opBitcast(
|
uint32_t opBitcast(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t operand);
|
uint32_t operand);
|
||||||
@ -179,6 +185,22 @@ namespace dxvk {
|
|||||||
uint32_t indexCount,
|
uint32_t indexCount,
|
||||||
const uint32_t* indexArray);
|
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 opFunctionCall(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t functionId,
|
uint32_t functionId,
|
||||||
@ -200,9 +222,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint32_t m_id = 1;
|
uint32_t m_id = 1;
|
||||||
|
uint32_t m_instExtGlsl450 = 0;
|
||||||
|
|
||||||
SpirvCodeBuffer m_capabilities;
|
SpirvCodeBuffer m_capabilities;
|
||||||
|
SpirvCodeBuffer m_instExt;
|
||||||
SpirvCodeBuffer m_memoryModel;
|
SpirvCodeBuffer m_memoryModel;
|
||||||
SpirvCodeBuffer m_entryPoints;
|
SpirvCodeBuffer m_entryPoints;
|
||||||
SpirvCodeBuffer m_execModeInfo;
|
SpirvCodeBuffer m_execModeInfo;
|
||||||
@ -217,6 +241,8 @@ namespace dxvk {
|
|||||||
uint32_t argCount,
|
uint32_t argCount,
|
||||||
const uint32_t* argIds);
|
const uint32_t* argIds);
|
||||||
|
|
||||||
|
void instImportGlsl450();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user