Add support for extended instruction sets

* Implement a few instructions in GLSL.std.450
This commit is contained in:
baldurk
2020-04-08 10:49:19 +01:00
parent 27bd045ea3
commit 57400e1bf8
8 changed files with 327 additions and 1 deletions
@@ -99,6 +99,7 @@ set(sources
spirv_compile.cpp
spirv_compile.h
spirv_debug_setup.cpp
spirv_debug_glsl450.cpp
spirv_debug.cpp
spirv_debug.h
spirv_reflect.cpp
@@ -157,6 +157,7 @@
<ForcedIncludeFiles>precompiled.h</ForcedIncludeFiles>
</ClCompile>
<ClCompile Include="spirv_debug.cpp" />
<ClCompile Include="spirv_debug_glsl450.cpp" />
<ClCompile Include="spirv_debug_setup.cpp" />
<ClCompile Include="spirv_disassemble.cpp">
<WarningLevel>Level4</WarningLevel>
@@ -145,6 +145,7 @@
<ClCompile Include="spirv_processor.cpp" />
<ClCompile Include="spirv_debug_setup.cpp" />
<ClCompile Include="spirv_debug.cpp" />
<ClCompile Include="spirv_debug_glsl450.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\3rdparty\glslang\OGLCompilersDLL\InitializeDll.h">
@@ -781,6 +781,53 @@ void ThreadState::StepNext(ShaderDebugState *state,
break;
}
//////////////////////////////////////////////////////////////////////////////
//
// Extended instruction set handling
//
//////////////////////////////////////////////////////////////////////////////
case Op::ExtInst:
{
Id result = Id::fromWord(it.word(2));
Id extinst = Id::fromWord(it.word(3));
if(global.extInsts.find(extinst) == global.extInsts.end())
{
RDCERR("Unknown extended instruction set %u", extinst.value());
break;
}
const ExtInstDispatcher &dispatch = global.extInsts[extinst];
// ignore nonsemantic instructions
if(dispatch.nonsemantic)
break;
uint32_t instruction = it.word(4);
if(instruction >= dispatch.functions.size())
{
RDCERR("Unsupported instruction %u in set %s (only %zu instructions defined)", instruction,
dispatch.name.c_str(), dispatch.functions.size());
break;
}
if(dispatch.functions[instruction] == NULL)
{
RDCWARN("Unimplemented extended instruction %s::%s", dispatch.name.c_str(),
dispatch.names[instruction].c_str());
break;
}
rdcarray<Id> params;
for(size_t i = 5; i < it.size(); i++)
params.push_back(Id::fromWord(it.word(i)));
SetDst(state, result, dispatch.functions[instruction](*this, params));
break;
}
//////////////////////////////////////////////////////////////////////////////
//
// Comparison opcodes
+18 -1
View File
@@ -58,12 +58,28 @@ public:
uint32_t component) = 0;
};
struct ThreadState;
typedef ShaderVariable (*ExtInstImpl)(ThreadState &, const rdcarray<Id> &);
struct ExtInstDispatcher
{
rdcstr name;
bool nonsemantic = false;
rdcarray<rdcstr> names;
rdcarray<ExtInstImpl> functions;
};
void ConfigureGLSLStd450(ExtInstDispatcher &extinst);
struct GlobalState
{
public:
GlobalState() {}
// allocated storage for opaque uniform blocks, does not change over the course of debugging
rdcarray<ShaderVariable> constantBlocks;
SparseIdMap<ExtInstDispatcher> extInsts;
};
struct StackFrame
@@ -132,8 +148,9 @@ struct ThreadState
uint32_t workgroupIndex;
bool done;
private:
const ShaderVariable &GetSrc(Id id);
private:
void SetDst(ShaderDebugState *state, Id id, const ShaderVariable &val);
void ProcessScopeChange(ShaderDebugState &state, const rdcarray<Id> &oldLive,
const rdcarray<Id> &newLive);
@@ -0,0 +1,155 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2020 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "spirv_debug.h"
#include <math.h>
#if defined(_MSC_VER)
#define finite _finite
#endif
namespace rdcspv
{
namespace glsl
{
#define CHECK_PARAMS(n) \
if(params.size() != n) \
{ \
RDCERR("Unexpected number of parameters (%zu) to %s, expected %u", params.size(), \
__PRETTY_FUNCTION_SIGNATURE__, n); \
return ShaderVariable(); \
}
ShaderVariable FAbs(ThreadState &state, const rdcarray<Id> &params)
{
CHECK_PARAMS(1);
ShaderVariable var = state.GetSrc(params[0]);
for(uint32_t c = 0; c < var.columns; c++)
var.value.fv[c] = fabs(var.value.fv[c]);
return var;
}
ShaderVariable Floor(ThreadState &state, const rdcarray<Id> &params)
{
CHECK_PARAMS(1);
ShaderVariable var = state.GetSrc(params[0]);
for(uint32_t c = 0; c < var.columns; c++)
var.value.fv[c] = floor(var.value.fv[c]);
return var;
}
ShaderVariable Pow(ThreadState &state, const rdcarray<Id> &params)
{
CHECK_PARAMS(2);
ShaderVariable var = state.GetSrc(params[0]);
ShaderVariable y = state.GetSrc(params[1]);
for(uint32_t c = 0; c < var.columns; c++)
var.value.fv[c] = powf(var.value.fv[c], y.value.fv[c]);
return var;
}
ShaderVariable FMix(ThreadState &state, const rdcarray<Id> &params)
{
CHECK_PARAMS(3);
ShaderVariable var = state.GetSrc(params[0]);
ShaderVariable y = state.GetSrc(params[1]);
ShaderVariable a = state.GetSrc(params[2]);
for(uint32_t c = 0; c < var.columns; c++)
{
float xf = var.value.fv[c];
float yf = y.value.fv[c];
float af = a.value.fv[c];
var.value.fv[c] = xf * (1 - af) + yf * af;
}
return var;
}
ShaderVariable Normalize(ThreadState &state, const rdcarray<Id> &params)
{
CHECK_PARAMS(1);
ShaderVariable var = state.GetSrc(params[0]);
float sqrlength = 0.0f;
for(uint32_t c = 0; c < var.columns; c++)
sqrlength += (var.value.fv[c] * var.value.fv[c]);
float invlength = 1.0f / sqrt(sqrlength);
for(uint32_t c = 0; c < var.columns; c++)
var.value.fv[c] *= invlength;
return var;
}
ShaderVariable Cross(ThreadState &state, const rdcarray<Id> &params)
{
CHECK_PARAMS(2);
ShaderVariable x = state.GetSrc(params[0]);
ShaderVariable y = state.GetSrc(params[1]);
RDCASSERT(x.columns == 3 && y.columns == 3, x.columns, y.columns);
ShaderVariable var = x;
var.value.fv[0] = x.value.fv[1] * y.value.fv[2] - y.value.fv[1] * x.value.fv[2];
var.value.fv[1] = x.value.fv[2] * y.value.fv[0] - y.value.fv[2] * x.value.fv[0];
var.value.fv[2] = x.value.fv[0] * y.value.fv[1] - y.value.fv[0] * x.value.fv[1];
return var;
}
}; // namespace glsl
void ConfigureGLSLStd450(ExtInstDispatcher &extinst)
{
extinst.names.resize((size_t)GLSLstd450::Max);
for(size_t i = 0; i < extinst.names.size(); i++)
extinst.names[i] = ToStr(GLSLstd450(i));
extinst.functions.resize(extinst.names.size());
#define EXT(func) extinst.functions[(uint32_t)GLSLstd450::func] = &glsl::func;
EXT(FAbs);
EXT(Floor);
EXT(Pow);
EXT(FMix);
EXT(Cross);
EXT(Normalize);
}
}; // namespace rdcspv
@@ -200,6 +200,38 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader
}
}
for(auto it = extSets.begin(); it != extSets.end(); it++)
{
Id id = it->first;
const rdcstr &setname = it->second;
if(setname == "GLSL.std.450")
{
ExtInstDispatcher extinst;
extinst.name = setname;
ConfigureGLSLStd450(extinst);
global.extInsts[id] = extinst;
}
else if(setname.beginsWith("NonSemantic."))
{
ExtInstDispatcher extinst;
extinst.name = setname;
extinst.nonsemantic = true;
global.extInsts[id] = extinst;
}
else
{
RDCERR("Unsupported extended instruction set: %s", setname.c_str());
return new ShaderDebugTrace;
}
}
for(const rdcstr &e : extensions)
{
if(e == "SPV_GOOGLE_decorate_string" || e == "SPV_GOOGLE_hlsl_functionality1")
@@ -192,6 +192,78 @@ void main()
Color = dFdyFine(vec4(inpos, inposIncreased));
break;
}
case 13:
{
Color = vec4(abs(posone*2.5f), abs(negone*2.5f), abs(zerof*2.5f), 1.0f);
break;
}
case 14:
{
Color = vec4(pow(posone*2.5f, posone*1.3f), pow(posone*2.5f, posone*0.45f),
pow(vec2(posone*2.5f, posone*1.3f), vec2(posone*0.9f, posone*8.5f)));
break;
}
case 15:
{
Color = vec4(normalize(posone*2.5f), normalize(posone), normalize(negone), 1.0f);
break;
}
case 16:
{
Color = vec4(normalize(vec2(posone*2.5f, negone*1.8f)), normalize(vec2(posone*8.5f, negone*7.1f)));
break;
}
case 17:
{
Color = vec4(normalize(vec3(posone*2.5f, negone*1.8f, posone*8.5f)), 1.0f);
break;
}
case 18:
{
Color = normalize(vec4(posone*2.5f, negone*1.8f, posone*8.5f, negone*5.2f));
break;
}
case 19:
{
Color = vec4(floor(posone*2.5f), floor(posone*2.4f), floor(posone*2.6f), floor(zerof));
break;
}
case 20:
{
Color = vec4(floor(negone*2.5f), floor(negone*2.4f), floor(negone*2.6f), 1.0f);
break;
}
case 21:
{
Color = vec4(mix(posone*1.1f, posone*3.3f, 0.5f),
mix(posone*1.1f, posone*3.3f, 0.2f),
mix(posone*1.1f, posone*3.3f, 0.8f),
1.0f);
break;
}
case 22:
{
Color = vec4(mix(posone*1.1f, posone*3.3f, 1.5f),
mix(posone*1.1f, posone*3.3f, -0.3f),
0.0f,
1.0f);
break;
}
case 23:
{
Color = vec4(mix(posone*3.3f, posone*1.1f, 0.5f),
mix(posone*3.3f, posone*1.1f, 0.2f),
mix(posone*3.3f, posone*1.1f, 0.8f),
1.0f);
break;
}
case 24:
{
vec3 a = vec3(posone*2.5f, negone*1.8f, posone*8.5f);
vec3 b = vec3(negone*6.3f, posone*3.2f, negone*0.4f);
Color = vec4(cross(a, b), 1.0f);
break;
}
default: break;
}
}