https://github.com/shader-slang/slang
Tip revision: e59516fa8c3a16eb7b99a928c5b85b97bf44fd72 authored by Yong He on 01 February 2022, 00:26:03 UTC
Revise entrypoint renaming interface. (#2113)
Revise entrypoint renaming interface. (#2113)
Tip revision: e59516f
slang-ir-specialize-buffer-load-arg.cpp
// slang-ir-specialize-buffer-load-arg.cpp
#include "slang-ir-specialize-buffer-load-arg.h"
#include "slang-ir.h"
#include "slang-ir-insts.h"
#include "slang-ir-specialize-function-call.h"
namespace Slang
{
// This file implements a pass that translates function call sites where
// the result of a buffer load from a global shader parameter (e.g., a
// global constant buffer) is being passed through to the callee. It
// replaces those with calls to specialized callee functions that directly
// reference the chosen global.
//
// As swith most of our IR passes, we encapsulate the logic here in a context
// type so that the data that needs to be shared throughout the pass can
// be conveniently scoped.
struct FuncBufferLoadSpecializationCondition : FunctionCallSpecializeCondition
{
typedef FunctionCallSpecializeCondition Super;
virtual bool doesParamWantSpecialization(IRParam* param, IRInst* arg)
{
// We only want to specialize for `struct` types and not base types.
//
// TODO: We might want to consider some criteria here for the "large-ness"
// of a structure (in terms of bytes and/or fields), so that we don't
// eliminate loads of sufficiently small types (which are cheap to pass
// by value).
//
auto paramType = param->getDataType();
if(!as<IRStructType>(paramType))
return false;
// We also only want to specialize for arguments that are a load
// from some kind of global shader parameter.
//
IRInst* a = arg;
if (auto argLoad = as<IRLoad>(arg))
{
a = argLoad->getPtr();
}
else
{
return false;
}
// We want to handle loads from a shader parameter that is an array
// of buffers, and not just a single global buffer.
//
while (auto argGetElement = as<IRGetElement>(a))
{
a = argGetElement->getBase();
}
// The "root" of the parameter must be a reference to a global-scope
// shader parameter, so that we know we can substitute it into the callee.
//
if (auto argGlobalParam = as<IRGlobalParam>(a))
{
return true;
}
else
{
return false;
}
// TODO: There are other patterns that we could attempt to optimize here.
// For example, this logic only handles loads of the *entire* contents of
// a buffer, so it would miss:
//
// * A load of a large structure from field in a constant buffer, so that
// the value loaded is not the entire buffer contents.
//
// * A load of a large structure from a structured buffer, or any other kind
// of buffer that requires an index.
//
// * Any resource load that is not expressed at the IR level with a `load`
// instruction (e.g., those that might use an intrinsic function).
//
}
};
void specializeFuncsForBufferLoadArgs(
BackEndCompileRequest* compileRequest,
TargetRequest* targetRequest,
IRModule* module)
{
FuncBufferLoadSpecializationCondition condition;
specializeFunctionCalls(compileRequest, targetRequest, module, &condition);
}
}