mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 05:52:11 +01:00
[spirv] Added SpirvModule class to generate SPIR-V code
This commit is contained in:
parent
294586eeb3
commit
200da4cf60
@ -4,7 +4,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
DxbcCompiler::DxbcCompiler(DxbcProgramVersion version)
|
DxbcCompiler::DxbcCompiler(DxbcProgramVersion version)
|
||||||
: m_version(version) {
|
: m_version(version) {
|
||||||
m_entryPointId = m_counter.nextId();
|
m_entryPointId = m_module.allocateId();
|
||||||
|
|
||||||
this->declareCapabilities();
|
this->declareCapabilities();
|
||||||
this->declareMemoryModel();
|
this->declareMemoryModel();
|
||||||
@ -21,7 +21,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
switch (token.opcode()) {
|
switch (token.opcode()) {
|
||||||
case DxbcOpcode::DclThreadGroup: {
|
case DxbcOpcode::DclThreadGroup: {
|
||||||
m_spvEntryPoints.setLocalSize(
|
m_module.setLocalSize(
|
||||||
m_entryPointId,
|
m_entryPointId,
|
||||||
ins.getArgWord(0),
|
ins.getArgWord(0),
|
||||||
ins.getArgWord(1),
|
ins.getArgWord(1),
|
||||||
@ -37,33 +37,22 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
Rc<DxvkShader> DxbcCompiler::finalize() {
|
Rc<DxvkShader> DxbcCompiler::finalize() {
|
||||||
SpirvCodeBuffer codeBuffer;
|
|
||||||
codeBuffer.putHeader(m_counter.numIds());
|
|
||||||
codeBuffer.append(m_spvCapabilities.code());
|
|
||||||
codeBuffer.append(m_spvEntryPoints.code());
|
|
||||||
codeBuffer.append(m_spvDebugInfo.code());
|
|
||||||
codeBuffer.append(m_spvDecorations.code());
|
|
||||||
codeBuffer.append(m_spvTypeInfo.code());
|
|
||||||
codeBuffer.append(m_spvConstants.code());
|
|
||||||
codeBuffer.append(m_spvVariables.code());
|
|
||||||
codeBuffer.append(m_spvCode);
|
|
||||||
|
|
||||||
return new DxvkShader(m_version.shaderStage(),
|
return new DxvkShader(m_version.shaderStage(),
|
||||||
std::move(codeBuffer), 0, nullptr);
|
m_module.compile(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::declareCapabilities() {
|
void DxbcCompiler::declareCapabilities() {
|
||||||
m_spvCapabilities.enable(spv::CapabilityShader);
|
m_module.enableCapability(spv::CapabilityShader);
|
||||||
|
|
||||||
switch (m_version.type()) {
|
switch (m_version.type()) {
|
||||||
case DxbcProgramType::GeometryShader:
|
case DxbcProgramType::GeometryShader:
|
||||||
m_spvCapabilities.enable(spv::CapabilityGeometry);
|
m_module.enableCapability(spv::CapabilityGeometry);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DxbcProgramType::HullShader:
|
case DxbcProgramType::HullShader:
|
||||||
case DxbcProgramType::DomainShader:
|
case DxbcProgramType::DomainShader:
|
||||||
m_spvCapabilities.enable(spv::CapabilityTessellation);
|
m_module.enableCapability(spv::CapabilityTessellation);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -73,7 +62,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::declareMemoryModel() {
|
void DxbcCompiler::declareMemoryModel() {
|
||||||
m_spvEntryPoints.setMemoryModel(
|
m_module.setMemoryModel(
|
||||||
spv::AddressingModelLogical,
|
spv::AddressingModelLogical,
|
||||||
spv::MemoryModelGLSL450);
|
spv::MemoryModelGLSL450);
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,7 @@
|
|||||||
|
|
||||||
#include "dxbc_chunk_shex.h"
|
#include "dxbc_chunk_shex.h"
|
||||||
|
|
||||||
#include "../spirv/gen/spirv_gen_capability.h"
|
#include "../spirv/spirv_module.h"
|
||||||
#include "../spirv/gen/spirv_gen_constant.h"
|
|
||||||
#include "../spirv/gen/spirv_gen_debuginfo.h"
|
|
||||||
#include "../spirv/gen/spirv_gen_decoration.h"
|
|
||||||
#include "../spirv/gen/spirv_gen_entrypoint.h"
|
|
||||||
#include "../spirv/gen/spirv_gen_typeinfo.h"
|
|
||||||
#include "../spirv/gen/spirv_gen_variable.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
@ -47,16 +41,7 @@ namespace dxvk {
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
DxbcProgramVersion m_version;
|
DxbcProgramVersion m_version;
|
||||||
SpirvIdCounter m_counter;
|
SpirvModule m_module;
|
||||||
|
|
||||||
SpirvCapabilities m_spvCapabilities;
|
|
||||||
SpirvEntryPoint m_spvEntryPoints;
|
|
||||||
SpirvDebugInfo m_spvDebugInfo;
|
|
||||||
SpirvDecorations m_spvDecorations;
|
|
||||||
SpirvTypeInfo m_spvTypeInfo;
|
|
||||||
SpirvConstants m_spvConstants;
|
|
||||||
SpirvVariables m_spvVariables;
|
|
||||||
SpirvCodeBuffer m_spvCode;
|
|
||||||
|
|
||||||
uint32_t m_entryPointId = 0;
|
uint32_t m_entryPointId = 0;
|
||||||
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
#include "spirv_gen_capability.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
SpirvCapabilities:: SpirvCapabilities() { }
|
|
||||||
SpirvCapabilities::~SpirvCapabilities() { }
|
|
||||||
|
|
||||||
|
|
||||||
void SpirvCapabilities::enable(spv::Capability cap) {
|
|
||||||
// Scan the generated instructions to check
|
|
||||||
// whether we already enabled the capability.
|
|
||||||
for (auto ins : m_code) {
|
|
||||||
if (ins.opCode() == spv::OpCapability && ins.arg(1) == cap)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_code.putIns (spv::OpCapability, 2);
|
|
||||||
m_code.putWord(cap);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../spirv_code_buffer.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief SPIR-V capability set
|
|
||||||
*
|
|
||||||
* Holds a code buffer solely for the \c OpCapability
|
|
||||||
* instructions in the generated SPIR-V shader module.
|
|
||||||
*/
|
|
||||||
class SpirvCapabilities {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SpirvCapabilities();
|
|
||||||
~SpirvCapabilities();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Code buffer
|
|
||||||
*
|
|
||||||
* Code buffer that contains the
|
|
||||||
* \c OpCapability instructions.
|
|
||||||
* \returns Code buffer
|
|
||||||
*/
|
|
||||||
const SpirvCodeBuffer& code() const {
|
|
||||||
return m_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Enables a capability
|
|
||||||
*
|
|
||||||
* If the given capability has not been explicitly
|
|
||||||
* enabled yet, this will generate an \c OpCapability
|
|
||||||
* instruction for the given capability.
|
|
||||||
* \param [in] cap The capability
|
|
||||||
*/
|
|
||||||
void enable(spv::Capability cap);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
SpirvCodeBuffer m_code;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "spirv_gen_constant.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
SpirvConstants:: SpirvConstants() { }
|
|
||||||
SpirvConstants::~SpirvConstants() { }
|
|
||||||
|
|
||||||
|
|
||||||
SpirvCodeBuffer SpirvConstants::code() const {
|
|
||||||
return m_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../spirv_code_buffer.h"
|
|
||||||
|
|
||||||
#include "spirv_gen_id.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief SPIR-V constant generator
|
|
||||||
*
|
|
||||||
* Provides convenient methods to
|
|
||||||
* generate SPIR-V constants.
|
|
||||||
*/
|
|
||||||
class SpirvConstants {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SpirvConstants();
|
|
||||||
~SpirvConstants();
|
|
||||||
|
|
||||||
SpirvCodeBuffer code() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
SpirvCodeBuffer m_code;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#include "spirv_gen_debuginfo.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
SpirvDebugInfo:: SpirvDebugInfo() { }
|
|
||||||
SpirvDebugInfo::~SpirvDebugInfo() { }
|
|
||||||
|
|
||||||
|
|
||||||
void SpirvDebugInfo::assignName(
|
|
||||||
uint32_t id,
|
|
||||||
const char* name) {
|
|
||||||
m_code.putIns (spv::OpName, 2 + m_code.strLen(name));
|
|
||||||
m_code.putWord(id);
|
|
||||||
m_code.putStr (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../spirv_code_buffer.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief SPIR-V debug info generator
|
|
||||||
*
|
|
||||||
* Can be used to assign names to result IDs,
|
|
||||||
* such as variables, for debugging purposes.
|
|
||||||
*/
|
|
||||||
class SpirvDebugInfo {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SpirvDebugInfo();
|
|
||||||
~SpirvDebugInfo();
|
|
||||||
|
|
||||||
const SpirvCodeBuffer& code() const {
|
|
||||||
return m_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
void assignName(
|
|
||||||
uint32_t id,
|
|
||||||
const char* name);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
SpirvCodeBuffer m_code;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
#include "spirv_gen_decoration.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
SpirvDecorations:: SpirvDecorations() { }
|
|
||||||
SpirvDecorations::~SpirvDecorations() { }
|
|
||||||
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../spirv_code_buffer.h"
|
|
||||||
|
|
||||||
#include "spirv_gen_id.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief SPIR-V decoration generator
|
|
||||||
*
|
|
||||||
* Generates instructions for descriptor
|
|
||||||
* bindings and builtin variable decorations.
|
|
||||||
*/
|
|
||||||
class SpirvDecorations {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SpirvDecorations();
|
|
||||||
~SpirvDecorations();
|
|
||||||
|
|
||||||
const SpirvCodeBuffer& code() const {
|
|
||||||
return m_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
SpirvCodeBuffer m_code;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
#include "spirv_gen_entrypoint.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
SpirvEntryPoint:: SpirvEntryPoint() { }
|
|
||||||
SpirvEntryPoint::~SpirvEntryPoint() { }
|
|
||||||
|
|
||||||
|
|
||||||
SpirvCodeBuffer SpirvEntryPoint::code() const {
|
|
||||||
SpirvCodeBuffer code;
|
|
||||||
code.append(m_memoryModel);
|
|
||||||
code.append(m_entryPoints);
|
|
||||||
code.append(m_execModeInfo);
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SpirvEntryPoint::setMemoryModel(
|
|
||||||
spv::AddressingModel addressModel,
|
|
||||||
spv::MemoryModel memoryModel) {
|
|
||||||
m_memoryModel.putIns (spv::OpMemoryModel, 3);
|
|
||||||
m_memoryModel.putWord (addressModel);
|
|
||||||
m_memoryModel.putWord (memoryModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SpirvEntryPoint::addEntryPoint(
|
|
||||||
uint32_t functionId,
|
|
||||||
spv::ExecutionModel execModel,
|
|
||||||
const char* name,
|
|
||||||
uint32_t interfaceCount,
|
|
||||||
const uint32_t* interfaceIds) {
|
|
||||||
m_entryPoints.putIns (spv::OpEntryPoint, 3 + m_entryPoints.strLen(name) + interfaceCount);
|
|
||||||
m_entryPoints.putWord (execModel);
|
|
||||||
m_entryPoints.putWord (functionId);
|
|
||||||
m_entryPoints.putStr (name);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < interfaceCount; i++)
|
|
||||||
m_entryPoints.putWord(interfaceIds[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SpirvEntryPoint::setLocalSize(
|
|
||||||
uint32_t functionId,
|
|
||||||
uint32_t x,
|
|
||||||
uint32_t y,
|
|
||||||
uint32_t z) {
|
|
||||||
m_execModeInfo.putIns (spv::OpExecutionMode, 6);
|
|
||||||
m_execModeInfo.putWord(functionId);
|
|
||||||
m_execModeInfo.putWord(spv::ExecutionModeLocalSize);
|
|
||||||
m_execModeInfo.putWord(x);
|
|
||||||
m_execModeInfo.putWord(y);
|
|
||||||
m_execModeInfo.putWord(z);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../spirv_code_buffer.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief SPIR-V entry point info
|
|
||||||
*
|
|
||||||
* Accumulates information about the entry
|
|
||||||
* point of the generated shader module,
|
|
||||||
* including execution mode info.
|
|
||||||
*/
|
|
||||||
class SpirvEntryPoint {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SpirvEntryPoint();
|
|
||||||
~SpirvEntryPoint();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Generates SPIR-V code
|
|
||||||
* \returns SPIR-V code buffer
|
|
||||||
*/
|
|
||||||
SpirvCodeBuffer code() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Sets memory model
|
|
||||||
*
|
|
||||||
* Generates an \c OpMemoryModel instruction.
|
|
||||||
* Only ever call this once, or otherwise the
|
|
||||||
* resulting shader will become undefined.
|
|
||||||
* \param [in] addressModel Address model
|
|
||||||
* \param [in] memoryModel Memory model
|
|
||||||
*/
|
|
||||||
void setMemoryModel(
|
|
||||||
spv::AddressingModel addressModel,
|
|
||||||
spv::MemoryModel memoryModel);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Adds an entry point
|
|
||||||
*
|
|
||||||
* Currently, DXVK expects there to be a single entry point
|
|
||||||
* with the name \c main. Do not create additional entry points.
|
|
||||||
* \param [in] functionId Entry point function ID
|
|
||||||
* \param [in] execModel Execution model for the function
|
|
||||||
* \param [in] name Entry point name that is used by Vulkan
|
|
||||||
* \param [in] interfaceCount Number of additional interface IDs
|
|
||||||
* \param [in] interfaceIds List of additional interface IDs
|
|
||||||
*/
|
|
||||||
void addEntryPoint(
|
|
||||||
uint32_t functionId,
|
|
||||||
spv::ExecutionModel execModel,
|
|
||||||
const char* name,
|
|
||||||
uint32_t interfaceCount,
|
|
||||||
const uint32_t* interfaceIds);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Enables early fragment tests
|
|
||||||
*/
|
|
||||||
void enableEarlyFragmentTests(
|
|
||||||
uint32_t functionId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Sets local work group size for a compute shader
|
|
||||||
*
|
|
||||||
* Adds a \c OpExecutionMode instruction that sets
|
|
||||||
* the local work group size for a compute shader.
|
|
||||||
* \param [in] functionId Entry point ID
|
|
||||||
* \param [in] x Number of threads in X direction
|
|
||||||
* \param [in] y Number of threads in Y direction
|
|
||||||
* \param [in] z Number of threads in Z direction
|
|
||||||
*/
|
|
||||||
void setLocalSize(
|
|
||||||
uint32_t functionId,
|
|
||||||
uint32_t x,
|
|
||||||
uint32_t y,
|
|
||||||
uint32_t z);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
SpirvCodeBuffer m_memoryModel;
|
|
||||||
SpirvCodeBuffer m_entryPoints;
|
|
||||||
SpirvCodeBuffer m_execModeInfo;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../spirv_include.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief SPIR-V ID counter
|
|
||||||
*
|
|
||||||
* Allocates IDs, starting at zero. This is meant
|
|
||||||
* to be used to allocate unique IDs during code
|
|
||||||
* generation.
|
|
||||||
*/
|
|
||||||
class SpirvIdCounter {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
uint32_t nextId() {
|
|
||||||
return ++m_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t numIds() const {
|
|
||||||
return m_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
uint32_t m_id = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
#include <array>
|
|
||||||
|
|
||||||
#include "spirv_gen_typeinfo.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
SpirvTypeInfo:: SpirvTypeInfo() { }
|
|
||||||
SpirvTypeInfo::~SpirvTypeInfo() { }
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeVoid(SpirvIdCounter& ids) {
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeVoid, 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeBool(SpirvIdCounter& ids) {
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeBool, 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeInt(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t width,
|
|
||||||
uint32_t isSigned) {
|
|
||||||
std::array<uint32_t, 2> args = {{ width, isSigned }};
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeInt, args.size(), args.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeFloat(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t width) {
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeFloat, 1, &width);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeVector(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t componentType,
|
|
||||||
uint32_t componentCount) {
|
|
||||||
std::array<uint32_t, 2> args = {{ componentType, componentCount }};
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeVector, args.size(), args.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeMatrix(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t colType,
|
|
||||||
uint32_t colCount) {
|
|
||||||
std::array<uint32_t, 2> args = {{ colType, colCount }};
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeMatrix, args.size(), args.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeArray(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t elementType,
|
|
||||||
uint32_t elementCount) {
|
|
||||||
std::array<uint32_t, 2> args = {{ elementType, elementCount }};
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeArray, args.size(), args.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeRuntimeArray(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t elementType) {
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeRuntimeArray, 1, &elementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typePointer(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
spv::StorageClass storageClass,
|
|
||||||
uint32_t type) {
|
|
||||||
std::array<uint32_t, 2> args = {{ storageClass, type }};
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypePointer, args.size(), args.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeFunction(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t returnType,
|
|
||||||
uint32_t argCount,
|
|
||||||
const uint32_t* argTypes) {
|
|
||||||
std::vector<uint32_t> args(argCount + 1);
|
|
||||||
args.at(0) = returnType;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < argCount; i++)
|
|
||||||
args.at(i + 1) = argTypes[i];
|
|
||||||
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeFunction,
|
|
||||||
args.size(), args.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::typeStruct(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t memberCount,
|
|
||||||
const uint32_t* memberTypes) {
|
|
||||||
return this->getTypeId(ids,
|
|
||||||
spv::OpTypeStruct,
|
|
||||||
memberCount,
|
|
||||||
memberTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvTypeInfo::getTypeId(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
spv::Op op,
|
|
||||||
uint32_t argCount,
|
|
||||||
const uint32_t* args) {
|
|
||||||
// Since the type info is stored in the code buffer,
|
|
||||||
// we can use the code buffer to look up type IDs as
|
|
||||||
// well. Result IDs are always stored as argument 1.
|
|
||||||
for (auto ins : m_code) {
|
|
||||||
bool match = ins.opCode() == op;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < argCount && match; i++)
|
|
||||||
match &= ins.arg(2 + i) == args[i];
|
|
||||||
|
|
||||||
if (match)
|
|
||||||
return ins.arg(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type not yet declared, create a new one.
|
|
||||||
uint32_t result = ids.nextId();
|
|
||||||
m_code.putIns (op, 2 + argCount);
|
|
||||||
m_code.putWord(result);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < argCount; i++)
|
|
||||||
m_code.putWord(args[i]);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../spirv_code_buffer.h"
|
|
||||||
|
|
||||||
#include "spirv_gen_id.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief SPIR-V type set
|
|
||||||
*
|
|
||||||
* Stores SPIR-V type definition so that
|
|
||||||
* each type will only be declared once.
|
|
||||||
*/
|
|
||||||
class SpirvTypeInfo {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SpirvTypeInfo();
|
|
||||||
~SpirvTypeInfo();
|
|
||||||
|
|
||||||
const SpirvCodeBuffer& code() const {
|
|
||||||
return m_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t typeVoid(
|
|
||||||
SpirvIdCounter& ids);
|
|
||||||
|
|
||||||
uint32_t typeBool(
|
|
||||||
SpirvIdCounter& ids);
|
|
||||||
|
|
||||||
uint32_t typeInt(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t width,
|
|
||||||
uint32_t isSigned);
|
|
||||||
|
|
||||||
uint32_t typeFloat(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t width);
|
|
||||||
|
|
||||||
uint32_t typeVector(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t componentType,
|
|
||||||
uint32_t componentCount);
|
|
||||||
|
|
||||||
uint32_t typeMatrix(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t colType,
|
|
||||||
uint32_t colCount);
|
|
||||||
|
|
||||||
uint32_t typeArray(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t elementType,
|
|
||||||
uint32_t elementCount);
|
|
||||||
|
|
||||||
uint32_t typeRuntimeArray(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t elementType);
|
|
||||||
|
|
||||||
uint32_t typePointer(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
spv::StorageClass storageClass,
|
|
||||||
uint32_t type);
|
|
||||||
|
|
||||||
uint32_t typeFunction(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t returnType,
|
|
||||||
uint32_t argCount,
|
|
||||||
const uint32_t* argTypes);
|
|
||||||
|
|
||||||
uint32_t typeStruct(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
uint32_t memberCount,
|
|
||||||
const uint32_t* memberTypes);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
SpirvCodeBuffer m_code;
|
|
||||||
|
|
||||||
uint32_t getTypeId(
|
|
||||||
SpirvIdCounter& ids,
|
|
||||||
spv::Op op,
|
|
||||||
uint32_t argCount,
|
|
||||||
const uint32_t* args);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
#include "spirv_gen_variable.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
SpirvVariables:: SpirvVariables() { }
|
|
||||||
SpirvVariables::~SpirvVariables() { }
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../spirv_code_buffer.h"
|
|
||||||
|
|
||||||
#include "spirv_gen_id.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief SPIR-V variable generator
|
|
||||||
*
|
|
||||||
* Generates global variable declarations.
|
|
||||||
*/
|
|
||||||
class SpirvVariables {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SpirvVariables();
|
|
||||||
~SpirvVariables();
|
|
||||||
|
|
||||||
const SpirvCodeBuffer& code() const {
|
|
||||||
return m_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
SpirvCodeBuffer m_code;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,13 +1,6 @@
|
|||||||
spirv_src = files([
|
spirv_src = files([
|
||||||
'spirv_code_buffer.cpp',
|
'spirv_code_buffer.cpp',
|
||||||
|
'spirv_module.cpp',
|
||||||
'gen/spirv_gen_capability.cpp',
|
|
||||||
'gen/spirv_gen_constant.cpp',
|
|
||||||
'gen/spirv_gen_debuginfo.cpp',
|
|
||||||
'gen/spirv_gen_decoration.cpp',
|
|
||||||
'gen/spirv_gen_entrypoint.cpp',
|
|
||||||
'gen/spirv_gen_typeinfo.cpp',
|
|
||||||
'gen/spirv_gen_variable.cpp',
|
|
||||||
])
|
])
|
||||||
|
|
||||||
spirv_lib = static_library('spirv', spirv_src,
|
spirv_lib = static_library('spirv', spirv_src,
|
||||||
|
372
src/spirv/spirv_module.cpp
Normal file
372
src/spirv/spirv_module.cpp
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
#include "spirv_module.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
SpirvModule:: SpirvModule() { }
|
||||||
|
SpirvModule::~SpirvModule() { }
|
||||||
|
|
||||||
|
|
||||||
|
SpirvCodeBuffer SpirvModule::compile() const {
|
||||||
|
SpirvCodeBuffer result;
|
||||||
|
result.putHeader(m_id);
|
||||||
|
result.append(m_capabilities);
|
||||||
|
result.append(m_memoryModel);
|
||||||
|
result.append(m_entryPoints);
|
||||||
|
result.append(m_execModeInfo);
|
||||||
|
result.append(m_debugNames);
|
||||||
|
result.append(m_annotations);
|
||||||
|
result.append(m_typeDefs);
|
||||||
|
result.append(m_constDefs);
|
||||||
|
result.append(m_variables);
|
||||||
|
result.append(m_code);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::allocateId() {
|
||||||
|
return ++m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::enableCapability(
|
||||||
|
spv::Capability capability) {
|
||||||
|
// Scan the generated instructions to check
|
||||||
|
// whether we already enabled the capability.
|
||||||
|
for (auto ins : m_capabilities) {
|
||||||
|
if (ins.opCode() == spv::OpCapability && ins.arg(1) == capability)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_capabilities.putIns (spv::OpCapability, 2);
|
||||||
|
m_capabilities.putWord(capability);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::addEntryPoint(
|
||||||
|
uint32_t entryPointId,
|
||||||
|
spv::ExecutionModel executionModel,
|
||||||
|
const char* name,
|
||||||
|
uint32_t interfaceCount,
|
||||||
|
const uint32_t* interfaceIds) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::setMemoryModel(
|
||||||
|
spv::AddressingModel addressModel,
|
||||||
|
spv::MemoryModel memoryModel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::enableEarlyFragmentTests(
|
||||||
|
uint32_t entryPointId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::setLocalSize(
|
||||||
|
uint32_t entryPointId,
|
||||||
|
uint32_t x,
|
||||||
|
uint32_t y,
|
||||||
|
uint32_t z) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::setDebugName(
|
||||||
|
uint32_t expressionId,
|
||||||
|
const char* debugName) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::constBool(
|
||||||
|
bool v) {
|
||||||
|
uint32_t typeId = this->defBoolType();
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_constDefs.putIns (v ? spv::OpConstantTrue : spv::OpConstantFalse, 3);
|
||||||
|
m_constDefs.putWord (typeId);
|
||||||
|
m_constDefs.putWord (resultId);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::consti32(
|
||||||
|
int32_t v) {
|
||||||
|
uint32_t typeId = this->defIntType(32, 1);
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_constDefs.putIns (spv::OpConstant, 4);
|
||||||
|
m_constDefs.putWord (typeId);
|
||||||
|
m_constDefs.putWord (resultId);
|
||||||
|
m_constDefs.putInt32(v);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::consti64(
|
||||||
|
int64_t v) {
|
||||||
|
uint32_t typeId = this->defIntType(64, 1);
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_constDefs.putIns (spv::OpConstant, 5);
|
||||||
|
m_constDefs.putWord (typeId);
|
||||||
|
m_constDefs.putWord (resultId);
|
||||||
|
m_constDefs.putInt64(v);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::constu32(
|
||||||
|
uint32_t v) {
|
||||||
|
uint32_t typeId = this->defIntType(32, 0);
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_constDefs.putIns (spv::OpConstant, 4);
|
||||||
|
m_constDefs.putWord (typeId);
|
||||||
|
m_constDefs.putWord (resultId);
|
||||||
|
m_constDefs.putInt32(v);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::constu64(
|
||||||
|
uint64_t v) {
|
||||||
|
uint32_t typeId = this->defIntType(64, 0);
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_constDefs.putIns (spv::OpConstant, 5);
|
||||||
|
m_constDefs.putWord (typeId);
|
||||||
|
m_constDefs.putWord (resultId);
|
||||||
|
m_constDefs.putInt64(v);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::constf32(
|
||||||
|
float v) {
|
||||||
|
uint32_t typeId = this->defFloatType(32);
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_constDefs.putIns (spv::OpConstant, 4);
|
||||||
|
m_constDefs.putWord (typeId);
|
||||||
|
m_constDefs.putWord (resultId);
|
||||||
|
m_constDefs.putFloat32(v);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::constf64(
|
||||||
|
double v) {
|
||||||
|
uint32_t typeId = this->defFloatType(64);
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_constDefs.putIns (spv::OpConstant, 5);
|
||||||
|
m_constDefs.putWord (typeId);
|
||||||
|
m_constDefs.putWord (resultId);
|
||||||
|
m_constDefs.putFloat64(v);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::constComposite(
|
||||||
|
uint32_t typeId,
|
||||||
|
uint32_t constCount,
|
||||||
|
const uint32_t* constIds) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_constDefs.putIns (spv::OpConstantComposite, 3 + constCount);
|
||||||
|
m_constDefs.putWord (typeId);
|
||||||
|
m_constDefs.putWord (resultId);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < constCount; i++)
|
||||||
|
m_constDefs.putWord(constIds[i]);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defVoidType() {
|
||||||
|
return this->defType(spv::OpTypeVoid, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defBoolType() {
|
||||||
|
return this->defType(spv::OpTypeBool, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defIntType(
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t isSigned) {
|
||||||
|
std::array<uint32_t, 2> args = { width, isSigned };
|
||||||
|
return this->defType(spv::OpTypeInt,
|
||||||
|
args.size(), args.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defFloatType(
|
||||||
|
uint32_t width) {
|
||||||
|
std::array<uint32_t, 1> args = { width };
|
||||||
|
return this->defType(spv::OpTypeFloat,
|
||||||
|
args.size(), args.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defVectorType(
|
||||||
|
uint32_t elementType,
|
||||||
|
uint32_t elementCount) {
|
||||||
|
std::array<uint32_t, 2> args = {
|
||||||
|
elementType,
|
||||||
|
elementCount
|
||||||
|
};
|
||||||
|
|
||||||
|
return this->defType(spv::OpTypeVector,
|
||||||
|
args.size(), args.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defMatrixType(
|
||||||
|
uint32_t columnType,
|
||||||
|
uint32_t columnCount) {
|
||||||
|
std::array<uint32_t, 2> args = {
|
||||||
|
columnType,
|
||||||
|
columnCount
|
||||||
|
};
|
||||||
|
|
||||||
|
return this->defType(spv::OpTypeMatrix,
|
||||||
|
args.size(), args.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defArrayType(
|
||||||
|
uint32_t typeId,
|
||||||
|
uint32_t length) {
|
||||||
|
std::array<uint32_t, 2> args = { typeId, length };
|
||||||
|
|
||||||
|
return this->defType(spv::OpTypeArray,
|
||||||
|
args.size(), args.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defRuntimeArrayType(
|
||||||
|
uint32_t typeId) {
|
||||||
|
std::array<uint32_t, 1> args = { typeId };
|
||||||
|
|
||||||
|
return this->defType(spv::OpTypeRuntimeArray,
|
||||||
|
args.size(), args.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defFunctionType(
|
||||||
|
uint32_t returnType,
|
||||||
|
uint32_t argCount,
|
||||||
|
const uint32_t* argTypes) {
|
||||||
|
std::vector<uint32_t> args;
|
||||||
|
args.push_back(returnType);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < argCount; i++)
|
||||||
|
args.push_back(argTypes[i]);
|
||||||
|
|
||||||
|
return this->defType(spv::OpTypeFunction,
|
||||||
|
args.size(), args.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defStructType(
|
||||||
|
uint32_t memberCount,
|
||||||
|
const uint32_t* memberTypes) {
|
||||||
|
return this->defType(spv::OpTypeStruct,
|
||||||
|
memberCount, memberTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defPointerType(
|
||||||
|
uint32_t variableType,
|
||||||
|
spv::StorageClass storageClass) {
|
||||||
|
std::array<uint32_t, 2> args = {
|
||||||
|
variableType,
|
||||||
|
storageClass,
|
||||||
|
};
|
||||||
|
|
||||||
|
return this->defType(spv::OpTypePointer,
|
||||||
|
args.size(), args.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::functionBegin(
|
||||||
|
uint32_t returnType,
|
||||||
|
uint32_t functionId,
|
||||||
|
uint32_t functionType,
|
||||||
|
spv::FunctionControlMask functionControl) {
|
||||||
|
m_code.putIns (spv::OpFunction, 5);
|
||||||
|
m_code.putWord(returnType);
|
||||||
|
m_code.putWord(functionId);
|
||||||
|
m_code.putWord(functionControl);
|
||||||
|
m_code.putWord(functionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::functionParameter(
|
||||||
|
uint32_t parameterType) {
|
||||||
|
uint32_t parameterId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpFunctionParameter, 3);
|
||||||
|
m_code.putWord(parameterType);
|
||||||
|
m_code.putWord(parameterId);
|
||||||
|
return parameterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::functionEnd() {
|
||||||
|
m_code.putIns (spv::OpFunctionEnd, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opFunctionCall(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t functionId,
|
||||||
|
uint32_t argCount,
|
||||||
|
const uint32_t* argIds) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpFunctionCall, 4 + argCount);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(functionId);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < argCount; i++)
|
||||||
|
m_code.putWord(argIds[i]);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::defType(
|
||||||
|
spv::Op op,
|
||||||
|
uint32_t argCount,
|
||||||
|
const uint32_t* argIds) {
|
||||||
|
// Since the type info is stored in the code buffer,
|
||||||
|
// we can use the code buffer to look up type IDs as
|
||||||
|
// well. Result IDs are always stored as argument 1.
|
||||||
|
for (auto ins : m_typeDefs) {
|
||||||
|
bool match = ins.opCode() == op;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < argCount && match; i++)
|
||||||
|
match &= ins.arg(2 + i) == argIds[i];
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
return ins.arg(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type not yet declared, create a new one.
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
m_typeDefs.putIns (op, 2 + argCount);
|
||||||
|
m_typeDefs.putWord(resultId);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < argCount; i++)
|
||||||
|
m_typeDefs.putWord(argIds[i]);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
157
src/spirv/spirv_module.h
Normal file
157
src/spirv/spirv_module.h
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "spirv_code_buffer.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief SPIR-V module
|
||||||
|
*
|
||||||
|
* This class generates a code buffer containing a full
|
||||||
|
* SPIR-V shader module. Ensures that the module layout
|
||||||
|
* is valid, as defined in the SPIR-V 1.0 specification,
|
||||||
|
* section 2.4 "Logical Layout of a Module".
|
||||||
|
*/
|
||||||
|
class SpirvModule {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
SpirvModule();
|
||||||
|
~SpirvModule();
|
||||||
|
|
||||||
|
SpirvCodeBuffer compile() const;
|
||||||
|
|
||||||
|
uint32_t allocateId();
|
||||||
|
|
||||||
|
void enableCapability(
|
||||||
|
spv::Capability capability);
|
||||||
|
|
||||||
|
void addEntryPoint(
|
||||||
|
uint32_t entryPointId,
|
||||||
|
spv::ExecutionModel executionModel,
|
||||||
|
const char* name,
|
||||||
|
uint32_t interfaceCount,
|
||||||
|
const uint32_t* interfaceIds);
|
||||||
|
|
||||||
|
void setMemoryModel(
|
||||||
|
spv::AddressingModel addressModel,
|
||||||
|
spv::MemoryModel memoryModel);
|
||||||
|
|
||||||
|
void enableEarlyFragmentTests(
|
||||||
|
uint32_t entryPointId);
|
||||||
|
|
||||||
|
void setLocalSize(
|
||||||
|
uint32_t entryPointId,
|
||||||
|
uint32_t x,
|
||||||
|
uint32_t y,
|
||||||
|
uint32_t z);
|
||||||
|
|
||||||
|
void setDebugName(
|
||||||
|
uint32_t expressionId,
|
||||||
|
const char* debugName);
|
||||||
|
|
||||||
|
uint32_t constBool(
|
||||||
|
bool v);
|
||||||
|
|
||||||
|
uint32_t consti32(
|
||||||
|
int32_t v);
|
||||||
|
|
||||||
|
uint32_t consti64(
|
||||||
|
int64_t v);
|
||||||
|
|
||||||
|
uint32_t constu32(
|
||||||
|
uint32_t v);
|
||||||
|
|
||||||
|
uint32_t constu64(
|
||||||
|
uint64_t v);
|
||||||
|
|
||||||
|
uint32_t constf32(
|
||||||
|
float v);
|
||||||
|
|
||||||
|
uint32_t constf64(
|
||||||
|
double v);
|
||||||
|
|
||||||
|
uint32_t constComposite(
|
||||||
|
uint32_t typeId,
|
||||||
|
uint32_t constCount,
|
||||||
|
const uint32_t* constIds);
|
||||||
|
|
||||||
|
uint32_t defVoidType();
|
||||||
|
|
||||||
|
uint32_t defBoolType();
|
||||||
|
|
||||||
|
uint32_t defIntType(
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t isSigned);
|
||||||
|
|
||||||
|
uint32_t defFloatType(
|
||||||
|
uint32_t width);
|
||||||
|
|
||||||
|
uint32_t defVectorType(
|
||||||
|
uint32_t elementType,
|
||||||
|
uint32_t elementCount);
|
||||||
|
|
||||||
|
uint32_t defMatrixType(
|
||||||
|
uint32_t columnType,
|
||||||
|
uint32_t columnCount);
|
||||||
|
|
||||||
|
uint32_t defArrayType(
|
||||||
|
uint32_t typeId,
|
||||||
|
uint32_t length);
|
||||||
|
|
||||||
|
uint32_t defRuntimeArrayType(
|
||||||
|
uint32_t typeId);
|
||||||
|
|
||||||
|
uint32_t defFunctionType(
|
||||||
|
uint32_t returnType,
|
||||||
|
uint32_t argCount,
|
||||||
|
const uint32_t* argTypes);
|
||||||
|
|
||||||
|
uint32_t defStructType(
|
||||||
|
uint32_t memberCount,
|
||||||
|
const uint32_t* memberTypes);
|
||||||
|
|
||||||
|
uint32_t defPointerType(
|
||||||
|
uint32_t variableType,
|
||||||
|
spv::StorageClass storageClass);
|
||||||
|
|
||||||
|
void functionBegin(
|
||||||
|
uint32_t returnType,
|
||||||
|
uint32_t functionId,
|
||||||
|
uint32_t functionType,
|
||||||
|
spv::FunctionControlMask functionControl);
|
||||||
|
|
||||||
|
uint32_t functionParameter(
|
||||||
|
uint32_t parameterType);
|
||||||
|
|
||||||
|
void functionEnd();
|
||||||
|
|
||||||
|
uint32_t opFunctionCall(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t functionId,
|
||||||
|
uint32_t argCount,
|
||||||
|
const uint32_t* argIds);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint32_t m_id = 0;
|
||||||
|
|
||||||
|
SpirvCodeBuffer m_capabilities;
|
||||||
|
SpirvCodeBuffer m_memoryModel;
|
||||||
|
SpirvCodeBuffer m_entryPoints;
|
||||||
|
SpirvCodeBuffer m_execModeInfo;
|
||||||
|
SpirvCodeBuffer m_debugNames;
|
||||||
|
SpirvCodeBuffer m_annotations;
|
||||||
|
SpirvCodeBuffer m_typeDefs;
|
||||||
|
SpirvCodeBuffer m_constDefs;
|
||||||
|
SpirvCodeBuffer m_variables;
|
||||||
|
SpirvCodeBuffer m_code;
|
||||||
|
|
||||||
|
uint32_t defType(
|
||||||
|
spv::Op op,
|
||||||
|
uint32_t argCount,
|
||||||
|
const uint32_t* argIds);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user