mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-18 13:54:16 +01:00
[dxbc] Added type info struct
This commit is contained in:
parent
77f38c33c4
commit
c1e9d3236f
0
src/dxbc/dxbc_annotation.cpp
Normal file
0
src/dxbc/dxbc_annotation.cpp
Normal file
0
src/dxbc/dxbc_annotation.h
Normal file
0
src/dxbc/dxbc_annotation.h
Normal file
25
src/dxbc/dxbc_capability.cpp
Normal file
25
src/dxbc/dxbc_capability.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "dxbc_capability.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxbcCapabilities:: DxbcCapabilities() { }
|
||||
DxbcCapabilities::~DxbcCapabilities() { }
|
||||
|
||||
|
||||
DxvkSpirvCodeBuffer DxbcCapabilities::code() const {
|
||||
DxvkSpirvCodeBuffer code;
|
||||
|
||||
for (auto cap : m_caps) {
|
||||
code.putIns (spv::OpCapability, 2);
|
||||
code.putWord(cap);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
void DxbcCapabilities::enable(spv::Capability cap) {
|
||||
m_caps.insert(cap);
|
||||
}
|
||||
|
||||
}
|
47
src/dxbc/dxbc_capability.h
Normal file
47
src/dxbc/dxbc_capability.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include "dxbc_include.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 DxbcCapabilities {
|
||||
|
||||
public:
|
||||
|
||||
DxbcCapabilities();
|
||||
~DxbcCapabilities();
|
||||
|
||||
/**
|
||||
* \brief Code buffer
|
||||
*
|
||||
* Code buffer that contains the
|
||||
* \c OpCapability instructions.
|
||||
* \returns Code buffer
|
||||
*/
|
||||
DxvkSpirvCodeBuffer code() const;
|
||||
|
||||
/**
|
||||
* \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:
|
||||
|
||||
std::unordered_set<spv::Capability> m_caps;
|
||||
|
||||
};
|
||||
|
||||
}
|
32
src/dxbc/dxbc_common.cpp
Normal file
32
src/dxbc/dxbc_common.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "dxbc_common.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
VkShaderStageFlagBits DxbcProgramVersion::shaderStage() const {
|
||||
switch (m_type) {
|
||||
case DxbcProgramType::PixelShader : return VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
case DxbcProgramType::VertexShader : return VK_SHADER_STAGE_VERTEX_BIT;
|
||||
case DxbcProgramType::GeometryShader : return VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||
case DxbcProgramType::HullShader : return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
|
||||
case DxbcProgramType::DomainShader : return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
|
||||
case DxbcProgramType::ComputeShader : return VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
}
|
||||
|
||||
throw DxvkError("DxbcProgramVersion::shaderStage: Unsupported program type");
|
||||
}
|
||||
|
||||
|
||||
spv::ExecutionModel DxbcProgramVersion::executionModel() const {
|
||||
switch (m_type) {
|
||||
case DxbcProgramType::PixelShader : return spv::ExecutionModelFragment;
|
||||
case DxbcProgramType::VertexShader : return spv::ExecutionModelVertex;
|
||||
case DxbcProgramType::GeometryShader : return spv::ExecutionModelGeometry;
|
||||
case DxbcProgramType::HullShader : return spv::ExecutionModelTessellationControl;
|
||||
case DxbcProgramType::DomainShader : return spv::ExecutionModelTessellationEvaluation;
|
||||
case DxbcProgramType::ComputeShader : return spv::ExecutionModelGLCompute;
|
||||
}
|
||||
|
||||
throw DxvkError("DxbcProgramVersion::executionModel: Unsupported program type");
|
||||
}
|
||||
|
||||
}
|
@ -59,6 +59,24 @@ namespace dxvk {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Vulkan shader stage
|
||||
*
|
||||
* The \c VkShaderStageFlagBits constant
|
||||
* that corresponds to the program type.
|
||||
* \returns Vulkan shaer stage
|
||||
*/
|
||||
VkShaderStageFlagBits shaderStage() const;
|
||||
|
||||
/**
|
||||
* \brief SPIR-V execution model
|
||||
*
|
||||
* The execution model that corresponds
|
||||
* to the Vulkan shader stage.
|
||||
* \returns SPIR-V execution model
|
||||
*/
|
||||
spv::ExecutionModel executionModel() const;
|
||||
|
||||
private:
|
||||
|
||||
uint8_t m_major = 0;
|
||||
|
@ -4,7 +4,26 @@ namespace dxvk {
|
||||
|
||||
DxbcCompiler::DxbcCompiler(DxbcProgramVersion version)
|
||||
: m_version(version) {
|
||||
this->enableCapability(spv::CapabilityShader);
|
||||
m_spvCapabilities.enable(spv::CapabilityShader);
|
||||
|
||||
m_spvEntryPoints.setMemoryModel(
|
||||
spv::AddressingModelLogical,
|
||||
spv::MemoryModelGLSL450);
|
||||
|
||||
auto id = m_counter.nextId();
|
||||
m_spvEntryPoints.addEntryPoint(id,
|
||||
spv::ExecutionModelGLCompute,
|
||||
"main", 0, nullptr);
|
||||
m_spvEntryPoints.setLocalSize(id, 64, 1, 1);
|
||||
auto ft = m_spvTypeInfo.typeFunction(m_counter,
|
||||
m_spvTypeInfo.typeVoid(m_counter), 0, nullptr);
|
||||
m_spvCode.putIns (spv::OpFunction, 5);
|
||||
m_spvCode.putWord (m_spvTypeInfo.typeVoid(m_counter));
|
||||
m_spvCode.putWord (id);
|
||||
m_spvCode.putWord (0);
|
||||
m_spvCode.putWord (ft);
|
||||
m_spvCode.putIns (spv::OpFunctionEnd, 1);
|
||||
m_entryPointId = m_counter.nextId();
|
||||
}
|
||||
|
||||
|
||||
@ -22,34 +41,13 @@ namespace dxvk {
|
||||
Rc<DxvkShader> DxbcCompiler::finalize() {
|
||||
DxvkSpirvCodeBuffer codeBuffer;
|
||||
codeBuffer.putHeader(m_counter.numIds());
|
||||
codeBuffer.append(m_spirvCapabilities);
|
||||
codeBuffer.append(m_spirvProgramCode);
|
||||
codeBuffer.append(m_spvCapabilities.code());
|
||||
codeBuffer.append(m_spvEntryPoints.code());
|
||||
codeBuffer.append(m_spvTypeInfo.code());
|
||||
codeBuffer.append(m_spvCode);
|
||||
|
||||
return new DxvkShader(this->shaderStage(),
|
||||
return new DxvkShader(m_version.shaderStage(),
|
||||
std::move(codeBuffer), 0, nullptr);
|
||||
}
|
||||
|
||||
|
||||
VkShaderStageFlagBits DxbcCompiler::shaderStage() const {
|
||||
switch (m_version.type()) {
|
||||
case DxbcProgramType::PixelShader : return VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
case DxbcProgramType::VertexShader : return VK_SHADER_STAGE_VERTEX_BIT;
|
||||
case DxbcProgramType::GeometryShader : return VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||
case DxbcProgramType::HullShader : return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
|
||||
case DxbcProgramType::DomainShader : return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
|
||||
case DxbcProgramType::ComputeShader : return VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
}
|
||||
|
||||
throw DxvkError("DxbcCompiler::shaderStage: Unknown program type");
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::enableCapability(spv::Capability cap) {
|
||||
if (m_capabilities.find(cap) == m_capabilities.end()) {
|
||||
m_spirvCapabilities.putIns (spv::OpCapability, 2);
|
||||
m_spirvCapabilities.putWord(cap);
|
||||
m_capabilities.insert(cap);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include "../dxvk/dxvk_shader.h"
|
||||
|
||||
#include "dxbc_capability.h"
|
||||
#include "dxbc_chunk_shex.h"
|
||||
#include "dxbc_entrypoint.h"
|
||||
#include "dxbc_typeinfo.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -39,14 +38,12 @@ namespace dxvk {
|
||||
DxbcProgramVersion m_version;
|
||||
DxvkSpirvIdCounter m_counter;
|
||||
|
||||
std::unordered_set<spv::Capability> m_capabilities;
|
||||
DxbcCapabilities m_spvCapabilities;
|
||||
DxbcEntryPoint m_spvEntryPoints;
|
||||
DxbcTypeInfo m_spvTypeInfo;
|
||||
DxvkSpirvCodeBuffer m_spvCode;
|
||||
|
||||
DxvkSpirvCodeBuffer m_spirvCapabilities;
|
||||
DxvkSpirvCodeBuffer m_spirvProgramCode;
|
||||
|
||||
VkShaderStageFlagBits shaderStage() const;
|
||||
|
||||
void enableCapability(spv::Capability cap);
|
||||
uint32_t m_entryPointId = 0;
|
||||
|
||||
};
|
||||
|
||||
|
56
src/dxbc/dxbc_entrypoint.cpp
Normal file
56
src/dxbc/dxbc_entrypoint.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "dxbc_entrypoint.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxbcEntryPoint:: DxbcEntryPoint() { }
|
||||
DxbcEntryPoint::~DxbcEntryPoint() { }
|
||||
|
||||
|
||||
DxvkSpirvCodeBuffer DxbcEntryPoint::code() const {
|
||||
DxvkSpirvCodeBuffer code;
|
||||
code.append(m_memoryModel);
|
||||
code.append(m_entryPoints);
|
||||
code.append(m_execModeInfo);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
void DxbcEntryPoint::setMemoryModel(
|
||||
spv::AddressingModel addressModel,
|
||||
spv::MemoryModel memoryModel) {
|
||||
m_memoryModel.putIns (spv::OpMemoryModel, 3);
|
||||
m_memoryModel.putWord (addressModel);
|
||||
m_memoryModel.putWord (memoryModel);
|
||||
}
|
||||
|
||||
|
||||
void DxbcEntryPoint::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 DxbcEntryPoint::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);
|
||||
}
|
||||
|
||||
}
|
82
src/dxbc/dxbc_entrypoint.h
Normal file
82
src/dxbc/dxbc_entrypoint.h
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxbc_include.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 DxbcEntryPoint {
|
||||
|
||||
public:
|
||||
|
||||
DxbcEntryPoint();
|
||||
~DxbcEntryPoint();
|
||||
|
||||
/**
|
||||
* \brief Generates SPIR-V code
|
||||
* \returns SPIR-V code buffer
|
||||
*/
|
||||
DxvkSpirvCodeBuffer 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 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:
|
||||
|
||||
DxvkSpirvCodeBuffer m_memoryModel;
|
||||
DxvkSpirvCodeBuffer m_entryPoints;
|
||||
DxvkSpirvCodeBuffer m_execModeInfo;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../dxvk/dxvk_shader.h"
|
||||
|
||||
#include "../util/com/com_guid.h"
|
||||
#include "../util/com/com_object.h"
|
||||
#include "../util/com/com_pointer.h"
|
||||
|
151
src/dxbc/dxbc_typeinfo.cpp
Normal file
151
src/dxbc/dxbc_typeinfo.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
#include "dxbc_typeinfo.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxbcTypeInfo:: DxbcTypeInfo() { }
|
||||
DxbcTypeInfo::~DxbcTypeInfo() { }
|
||||
|
||||
|
||||
DxvkSpirvCodeBuffer DxbcTypeInfo::code() const {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxbcTypeInfo::typeVoid(
|
||||
DxvkSpirvIdCounter& ids) {
|
||||
return this->getTypeId(ids,
|
||||
spv::OpTypeVoid, 0, nullptr);
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxbcTypeInfo::typeBool(
|
||||
DxvkSpirvIdCounter& ids) {
|
||||
return this->getTypeId(ids,
|
||||
spv::OpTypeBool, 0, nullptr);
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxbcTypeInfo::typeInt(
|
||||
DxvkSpirvIdCounter& 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 DxbcTypeInfo::typeFloat(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t width) {
|
||||
return this->getTypeId(ids,
|
||||
spv::OpTypeFloat, 1, &width);
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxbcTypeInfo::typeVector(
|
||||
DxvkSpirvIdCounter& 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 DxbcTypeInfo::typeMatrix(
|
||||
DxvkSpirvIdCounter& 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 DxbcTypeInfo::typeArray(
|
||||
DxvkSpirvIdCounter& 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 DxbcTypeInfo::typeRuntimeArray(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t elementType) {
|
||||
return this->getTypeId(ids,
|
||||
spv::OpTypeRuntimeArray, 1, &elementType);
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxbcTypeInfo::typePointer(
|
||||
DxvkSpirvIdCounter& 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 DxbcTypeInfo::typeFunction(
|
||||
DxvkSpirvIdCounter& 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 DxbcTypeInfo::typeStruct(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t memberCount,
|
||||
const uint32_t* memberTypes) {
|
||||
return this->getTypeId(ids,
|
||||
spv::OpTypeStruct,
|
||||
memberCount,
|
||||
memberTypes);
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxbcTypeInfo::getTypeId(
|
||||
DxvkSpirvIdCounter& 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
86
src/dxbc/dxbc_typeinfo.h
Normal file
86
src/dxbc/dxbc_typeinfo.h
Normal file
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
#include "dxbc_include.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief SPIR-V type set
|
||||
*
|
||||
* Stores SPIR-V type definition so that
|
||||
* each type will only be declared once.
|
||||
*/
|
||||
class DxbcTypeInfo {
|
||||
|
||||
public:
|
||||
|
||||
DxbcTypeInfo();
|
||||
~DxbcTypeInfo();
|
||||
|
||||
DxvkSpirvCodeBuffer code() const;
|
||||
|
||||
uint32_t typeVoid(
|
||||
DxvkSpirvIdCounter& ids);
|
||||
|
||||
uint32_t typeBool(
|
||||
DxvkSpirvIdCounter& ids);
|
||||
|
||||
uint32_t typeInt(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t width,
|
||||
uint32_t isSigned);
|
||||
|
||||
uint32_t typeFloat(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t width);
|
||||
|
||||
uint32_t typeVector(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t componentType,
|
||||
uint32_t componentCount);
|
||||
|
||||
uint32_t typeMatrix(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t colType,
|
||||
uint32_t colCount);
|
||||
|
||||
uint32_t typeArray(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t elementType,
|
||||
uint32_t elementCount);
|
||||
|
||||
uint32_t typeRuntimeArray(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t elementType);
|
||||
|
||||
uint32_t typePointer(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
spv::StorageClass storageClass,
|
||||
uint32_t type);
|
||||
|
||||
uint32_t typeFunction(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t returnType,
|
||||
uint32_t argCount,
|
||||
const uint32_t* argTypes);
|
||||
|
||||
uint32_t typeStruct(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
uint32_t memberCount,
|
||||
const uint32_t* memberTypes);
|
||||
|
||||
private:
|
||||
|
||||
DxvkSpirvCodeBuffer m_code;
|
||||
|
||||
uint32_t getTypeId(
|
||||
DxvkSpirvIdCounter& ids,
|
||||
spv::Op op,
|
||||
uint32_t argCount,
|
||||
const uint32_t* args);
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,9 +1,14 @@
|
||||
dxbc_src = files([
|
||||
'dxbc_annotation.cpp',
|
||||
'dxbc_capability.cpp',
|
||||
'dxbc_chunk_shex.cpp',
|
||||
'dxbc_common.cpp',
|
||||
'dxbc_compiler.cpp',
|
||||
'dxbc_entrypoint.cpp',
|
||||
'dxbc_header.cpp',
|
||||
'dxbc_module.cpp',
|
||||
'dxbc_reader.cpp',
|
||||
'dxbc_typeinfo.cpp',
|
||||
])
|
||||
|
||||
dxbc_lib = static_library('dxbc', dxbc_src,
|
||||
|
@ -33,7 +33,7 @@ namespace dxvk {
|
||||
uint32_t* dst = this->m_code.data();
|
||||
const uint32_t* src = other.m_code.data();
|
||||
|
||||
std::memcpy(dst + size, src, sizeof(uint32_t) * size);
|
||||
std::memcpy(dst + size, src, other.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "../dxvk_include.h"
|
||||
#include "dxvk_spirv_instruction.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -40,6 +40,27 @@ namespace dxvk {
|
||||
return m_code.size() * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Begin instruction iterator
|
||||
*
|
||||
* Points to the first instruction in the instruction
|
||||
* block. The header, if any, will be skipped over.
|
||||
* \returns Instruction iterator
|
||||
*/
|
||||
DxvkSpirvInstructionIterator begin() const {
|
||||
return DxvkSpirvInstructionIterator(m_code.data(), m_code.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief End instruction iterator
|
||||
*
|
||||
* Points to the end of the instruction block.
|
||||
* \returns Instruction iterator
|
||||
*/
|
||||
DxvkSpirvInstructionIterator end() const {
|
||||
return DxvkSpirvInstructionIterator(nullptr, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Merges two code buffers
|
||||
*
|
||||
|
@ -15,8 +15,8 @@ namespace dxvk {
|
||||
|
||||
public:
|
||||
|
||||
uint32_t nexId() {
|
||||
return m_id++;
|
||||
uint32_t nextId() {
|
||||
return ++m_id;
|
||||
}
|
||||
|
||||
uint32_t numIds() const {
|
||||
|
117
src/dxvk/spirv/dxvk_spirv_instruction.h
Normal file
117
src/dxvk/spirv/dxvk_spirv_instruction.h
Normal file
@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include <spirv/spirv.hpp>
|
||||
|
||||
#include "../dxvk_include.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief SPIR-V instruction
|
||||
*
|
||||
* Helps parsing a single instruction, providing
|
||||
* access to the op code, instruction length and
|
||||
* instruction arguments.
|
||||
*/
|
||||
class DxvkSpirvInstruction {
|
||||
|
||||
public:
|
||||
|
||||
DxvkSpirvInstruction() { }
|
||||
DxvkSpirvInstruction(
|
||||
const uint32_t* code, uint32_t size)
|
||||
: m_code(code), m_size(size) { }
|
||||
|
||||
/**
|
||||
* \brief SPIR-V Op code
|
||||
* \returns The op code
|
||||
*/
|
||||
spv::Op opCode() const {
|
||||
return static_cast<spv::Op>(
|
||||
m_code[0] & spv::OpCodeMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Instruction length
|
||||
* \returns Number of DWORDs
|
||||
*/
|
||||
uint32_t length() const {
|
||||
return m_code[0] >> spv::WordCountShift;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Argument value
|
||||
*
|
||||
* Retrieves an argument DWORD. Note that some instructions
|
||||
* take 64-bit arguments which require more than one DWORD.
|
||||
* Arguments start at index 1. Calling this method with an
|
||||
* argument ID of 0 will return the opcode token.
|
||||
* \param [in] id Argument index, starting at 1
|
||||
* \returns The argument value
|
||||
*/
|
||||
uint32_t arg(uint32_t id) const {
|
||||
return id < m_size ? m_code[id] : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t const* m_code = nullptr;
|
||||
uint32_t m_size = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief SPIR-V instruction
|
||||
*
|
||||
* Convenient iterator that can be used
|
||||
* to process raw SPIR-V shader code.
|
||||
*/
|
||||
class DxvkSpirvInstructionIterator {
|
||||
|
||||
public:
|
||||
|
||||
DxvkSpirvInstructionIterator() { }
|
||||
DxvkSpirvInstructionIterator(const uint32_t* code, uint32_t size)
|
||||
: m_code(size != 0 ? code : nullptr), m_size(size) {
|
||||
if ((size >= 5) && (m_code[0] == spv::MagicNumber))
|
||||
this->advance(5);
|
||||
}
|
||||
|
||||
DxvkSpirvInstructionIterator& operator ++ () {
|
||||
this->advance(DxvkSpirvInstruction(m_code, m_size).length());
|
||||
return *this;
|
||||
}
|
||||
|
||||
DxvkSpirvInstruction operator * () const {
|
||||
return DxvkSpirvInstruction(m_code, m_size);
|
||||
}
|
||||
|
||||
bool operator == (const DxvkSpirvInstructionIterator& other) const {
|
||||
return this->m_code == other.m_code
|
||||
&& this->m_size == other.m_size;
|
||||
}
|
||||
|
||||
bool operator != (const DxvkSpirvInstructionIterator& other) const {
|
||||
return this->m_code != other.m_code
|
||||
&& this->m_size != other.m_size;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t const* m_code = nullptr;
|
||||
uint32_t m_size = 0;
|
||||
|
||||
void advance(uint32_t n) {
|
||||
if (m_size >= n) {
|
||||
m_code += n;
|
||||
m_size -= n;
|
||||
} else {
|
||||
m_code = nullptr;
|
||||
m_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user