Shader linking i guess
This commit is contained in:
249
materialsystem/vulkan/rtlinker.cpp
Normal file
249
materialsystem/vulkan/rtlinker.cpp
Normal file
@@ -0,0 +1,249 @@
|
||||
#include "rtlinker.h"
|
||||
#define SPV_ENABLE_UTILITY_CODE
|
||||
#include "spirv/unified1/spirv.h"
|
||||
#include "rtlinker_gen.h"
|
||||
#include "tier2/ifilesystem.h"
|
||||
#include "tier1/utlstring.h"
|
||||
|
||||
#define MINI_SPIRV_IMPLEMENTATION
|
||||
#include "../minispv/minispv.h"
|
||||
|
||||
class CSpirvModule
|
||||
{
|
||||
CUtlVector<SpvCapability> m_capabilities;
|
||||
CUtlVector<CUtlString> m_extensions;
|
||||
CUtlVector<CUtlString> m_instructionImports;
|
||||
SpvAddressingModel m_addressingModel;
|
||||
SpvMemoryModel m_memoryModel;
|
||||
CUtlVector<CUtlString> m_entryPoints;
|
||||
|
||||
};
|
||||
|
||||
|
||||
void CVkShaderLinker::SetMainSpirv( uint32_t size, uint32_t *data )
|
||||
{
|
||||
m_main = (SpirvShader_t){size,data};
|
||||
}
|
||||
void CVkShaderLinker::AddSpirv( uint32_t size, uint32_t *data )
|
||||
{
|
||||
m_shaders.AppendTail((SpirvShader_t){size,data});
|
||||
}
|
||||
|
||||
#define SET_LAST(a) if ( a > last ) last = a;
|
||||
void CVkShaderLinker::Build()
|
||||
{
|
||||
mspv_module *mod = mspv_read_module(m_main.m_size, m_main.m_data);
|
||||
uint32_t last = 0;
|
||||
uint32_t current = 0;
|
||||
|
||||
for ( int i = 0; i < mod->types.count; i++ )
|
||||
{
|
||||
SET_LAST(mod->types.data[i].id);
|
||||
}
|
||||
|
||||
for ( int i = 0; i < mod->ext_instructions.count; i++ )
|
||||
{
|
||||
SET_LAST(mod->ext_instructions.data[i].id);
|
||||
}
|
||||
for ( int i = 0; i < mod->variables.count; i++ )
|
||||
{
|
||||
SET_LAST(mod->variables.data[i].result);
|
||||
SET_LAST(mod->variables.data[i].resulttype);
|
||||
}
|
||||
for ( int i = 0; i < mod->functions.count; i++ )
|
||||
{
|
||||
SET_LAST(mod->functions.data[i].result);
|
||||
mspv_function &f = mod->functions.data[i];
|
||||
for ( int u = 0; u < f.instructions.len; )
|
||||
{
|
||||
SpvOp op = (SpvOp)(f.instructions.data[u]&0xFFFF);
|
||||
uint32_t uOpLen = f.instructions.data[u]>>16;
|
||||
uint32_t uOpCount = SpvGetOperandCount(op);
|
||||
if (uOpCount == 0)
|
||||
{
|
||||
u+=uOpLen;
|
||||
continue;
|
||||
}
|
||||
ESpirvOperandType *peOps = (ESpirvOperandType *)V_malloc(uOpCount*sizeof(ESpirvOperandType));
|
||||
ESpirvOperandFlags *peFlags = (ESpirvOperandFlags *)V_malloc(uOpCount*sizeof(ESpirvOperandFlags));
|
||||
SpvGetOperands(op, peOps);
|
||||
SpvGetOperandFlags(op, peFlags);
|
||||
for ( int c = 0, uParam = 0; (c < uOpCount) && (c < uOpLen-1); c++ )
|
||||
{
|
||||
switch (peOps[c])
|
||||
{
|
||||
case k_ESpirv_RefId:
|
||||
case k_ESpirv_ResultId:
|
||||
case k_ESpirv_ResultTypeId:
|
||||
case k_ESpirv_ScopeId:
|
||||
case k_ESpirv_MemorySemanticsId:
|
||||
if (peFlags[uParam]==k_ESpirvOperandFlags_None)
|
||||
{
|
||||
uParam++;
|
||||
}
|
||||
SET_LAST(f.instructions.data[u+c+1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
u+=uOpLen;
|
||||
V_free(peOps);
|
||||
|
||||
}
|
||||
}
|
||||
current = last;
|
||||
|
||||
/* now we can combine shaders*/
|
||||
CUtlVector<uint32_t> functions = {};
|
||||
for (auto &shader: m_shaders)
|
||||
{
|
||||
mspv_module *s = mspv_read_module(shader.m_size, shader.m_data);
|
||||
for ( int i = 0; i < s->capabilities.count; i++ )
|
||||
{
|
||||
mspv_array_push(mod->capabilities, s->capabilities.data[i]);
|
||||
}
|
||||
for ( int i = 0; i < s->extensions.count; i++ )
|
||||
{
|
||||
mspv_array_push(mod->extensions, s->extensions.data[i]);
|
||||
}
|
||||
|
||||
for ( int i = 0; i < s->ext_instructions.count; i++ )
|
||||
{
|
||||
SET_LAST(s->ext_instructions.data[i].id);
|
||||
}
|
||||
|
||||
for ( int i = 0; i < s->entry_points.count; i++ )
|
||||
{
|
||||
functions.AppendTail(s->entry_points.data[i].id+current);
|
||||
SET_LAST(s->entry_points.data[i].id+current);
|
||||
}
|
||||
|
||||
for ( int i = 0; i < s->variables.count; i++ )
|
||||
{
|
||||
s->variables.data[i].result+=current;
|
||||
s->variables.data[i].resulttype+=current;
|
||||
SET_LAST(s->variables.data[i].result)
|
||||
SET_LAST(s->variables.data[i].resulttype)
|
||||
mspv_array_push(mod->variables, s->variables.data[i]);
|
||||
}
|
||||
for ( int i = 0; i < s->types.count; i++ )
|
||||
{
|
||||
s->types.data[i].id+=current;
|
||||
mspv_data_view &dv = s->types.data[i].dv;
|
||||
SET_LAST(s->types.data[i].id);
|
||||
|
||||
SpvOp op = (SpvOp)(dv.data[0]&0xFFFF);
|
||||
uint32_t uOpLen = dv.data[0]>>16;
|
||||
uint32_t uOpCount = SpvGetOperandCount(op);
|
||||
if (uOpCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ESpirvOperandType *peOps = (ESpirvOperandType *)V_malloc(uOpCount*sizeof(ESpirvOperandType));
|
||||
ESpirvOperandFlags *peFlags = (ESpirvOperandFlags *)V_malloc(uOpCount*sizeof(ESpirvOperandFlags));
|
||||
SpvGetOperands(op, peOps);
|
||||
SpvGetOperandFlags(op, peFlags);
|
||||
/* shift the stuff */
|
||||
for ( int c = 0, uParam = 0; (c < uOpCount) && (c < uOpLen-1); c++ )
|
||||
{
|
||||
switch (peOps[uParam])
|
||||
{
|
||||
case k_ESpirv_RefId:
|
||||
case k_ESpirv_ResultId:
|
||||
case k_ESpirv_ResultTypeId:
|
||||
case k_ESpirv_ScopeId:
|
||||
case k_ESpirv_MemorySemanticsId:
|
||||
|
||||
if (peFlags[uParam]==k_ESpirvOperandFlags_None)
|
||||
{
|
||||
dv.data[c+1]+=current;
|
||||
uParam++;
|
||||
|
||||
}
|
||||
if (peFlags[uParam]==k_ESpirvOperandFlags_Array)
|
||||
{
|
||||
dv.data[c+1]+=current;
|
||||
};
|
||||
SET_LAST(dv.data[c+1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
V_free(peFlags);
|
||||
V_free(peOps);
|
||||
mspv_array_push(mod->types, s->types.data[i]);
|
||||
}
|
||||
|
||||
for ( int i = 0; i < s->functions.count; i++ )
|
||||
{
|
||||
s->functions.data[i].result+=current;
|
||||
SET_LAST(s->functions.data[i].result);
|
||||
mspv_function &f = s->functions.data[i];
|
||||
for ( int u = 0; u < f.instructions.len; )
|
||||
{
|
||||
SpvOp op = (SpvOp)(f.instructions.data[u]&0xFFFF);
|
||||
uint32_t uOpLen = f.instructions.data[u]>>16;
|
||||
uint32_t uOpCount = SpvGetOperandCount(op);
|
||||
if (uOpCount == 0)
|
||||
{
|
||||
u+=uOpLen;
|
||||
continue;
|
||||
}
|
||||
ESpirvOperandType *peOps = (ESpirvOperandType *)V_malloc(uOpCount*sizeof(ESpirvOperandType));
|
||||
SpvGetOperands(op, peOps);
|
||||
/* shift the stuff */
|
||||
for ( int c = 0; c < uOpCount && c < (uOpLen-1); c++ )
|
||||
{
|
||||
switch (peOps[c])
|
||||
{
|
||||
case k_ESpirv_RefId:
|
||||
case k_ESpirv_ResultId:
|
||||
case k_ESpirv_ResultTypeId:
|
||||
case k_ESpirv_ScopeId:
|
||||
case k_ESpirv_MemorySemanticsId:
|
||||
|
||||
f.instructions.data[u+c+1]+=current;
|
||||
SET_LAST(f.instructions.data[u+c+1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
u+=uOpLen;
|
||||
V_free(peOps);
|
||||
|
||||
}
|
||||
mspv_array_push(mod->functions, s->functions.data[i]);
|
||||
}
|
||||
current = last;
|
||||
}
|
||||
|
||||
mspv_spv spv = mspv_write_module(mod);
|
||||
mspv_close_module(mod);
|
||||
m_out.m_data = spv.data;
|
||||
m_out.m_size = spv.count;
|
||||
|
||||
IFileHandle *ph = filesystem->Open("a.txt", FILEMODE_WRITE);
|
||||
filesystem->Write(ph, spv.data, spv.count*4);
|
||||
filesystem->Close(ph);
|
||||
|
||||
|
||||
mspv_array_destroy(spv);
|
||||
|
||||
|
||||
}
|
||||
uint32_t CVkShaderLinker::GetSize()
|
||||
{
|
||||
return m_out.m_size;
|
||||
|
||||
}
|
||||
uint32_t *CVkShaderLinker::GetData()
|
||||
{
|
||||
return m_out.m_data;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user