mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 10: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;
|
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:
|
private:
|
||||||
|
|
||||||
uint8_t m_major = 0;
|
uint8_t m_major = 0;
|
||||||
|
@ -4,7 +4,26 @@ namespace dxvk {
|
|||||||
|
|
||||||
DxbcCompiler::DxbcCompiler(DxbcProgramVersion version)
|
DxbcCompiler::DxbcCompiler(DxbcProgramVersion version)
|
||||||
: m_version(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() {
|
Rc<DxvkShader> DxbcCompiler::finalize() {
|
||||||
DxvkSpirvCodeBuffer codeBuffer;
|
DxvkSpirvCodeBuffer codeBuffer;
|
||||||
codeBuffer.putHeader(m_counter.numIds());
|
codeBuffer.putHeader(m_counter.numIds());
|
||||||
codeBuffer.append(m_spirvCapabilities);
|
codeBuffer.append(m_spvCapabilities.code());
|
||||||
codeBuffer.append(m_spirvProgramCode);
|
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);
|
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
|
#pragma once
|
||||||
|
|
||||||
#include <unordered_set>
|
#include "dxbc_capability.h"
|
||||||
|
|
||||||
#include "../dxvk/dxvk_shader.h"
|
|
||||||
|
|
||||||
#include "dxbc_chunk_shex.h"
|
#include "dxbc_chunk_shex.h"
|
||||||
|
#include "dxbc_entrypoint.h"
|
||||||
|
#include "dxbc_typeinfo.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
@ -39,14 +38,12 @@ namespace dxvk {
|
|||||||
DxbcProgramVersion m_version;
|
DxbcProgramVersion m_version;
|
||||||
DxvkSpirvIdCounter m_counter;
|
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;
|
uint32_t m_entryPointId = 0;
|
||||||
DxvkSpirvCodeBuffer m_spirvProgramCode;
|
|
||||||
|
|
||||||
VkShaderStageFlagBits shaderStage() const;
|
|
||||||
|
|
||||||
void enableCapability(spv::Capability cap);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include "../dxvk/dxvk_shader.h"
|
||||||
|
|
||||||
#include "../util/com/com_guid.h"
|
#include "../util/com/com_guid.h"
|
||||||
#include "../util/com/com_object.h"
|
#include "../util/com/com_object.h"
|
||||||
#include "../util/com/com_pointer.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_src = files([
|
||||||
|
'dxbc_annotation.cpp',
|
||||||
|
'dxbc_capability.cpp',
|
||||||
'dxbc_chunk_shex.cpp',
|
'dxbc_chunk_shex.cpp',
|
||||||
|
'dxbc_common.cpp',
|
||||||
'dxbc_compiler.cpp',
|
'dxbc_compiler.cpp',
|
||||||
|
'dxbc_entrypoint.cpp',
|
||||||
'dxbc_header.cpp',
|
'dxbc_header.cpp',
|
||||||
'dxbc_module.cpp',
|
'dxbc_module.cpp',
|
||||||
'dxbc_reader.cpp',
|
'dxbc_reader.cpp',
|
||||||
|
'dxbc_typeinfo.cpp',
|
||||||
])
|
])
|
||||||
|
|
||||||
dxbc_lib = static_library('dxbc', dxbc_src,
|
dxbc_lib = static_library('dxbc', dxbc_src,
|
||||||
|
@ -33,7 +33,7 @@ namespace dxvk {
|
|||||||
uint32_t* dst = this->m_code.data();
|
uint32_t* dst = this->m_code.data();
|
||||||
const uint32_t* src = other.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 <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../dxvk_include.h"
|
#include "dxvk_spirv_instruction.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
@ -40,6 +40,27 @@ namespace dxvk {
|
|||||||
return m_code.size() * sizeof(uint32_t);
|
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
|
* \brief Merges two code buffers
|
||||||
*
|
*
|
||||||
|
@ -15,8 +15,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
uint32_t nexId() {
|
uint32_t nextId() {
|
||||||
return m_id++;
|
return ++m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t numIds() const {
|
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