Merge branch 'topo' into loopgen-after-readable-order
This commit is contained in:
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(SOURCES
|
||||
GlslangToSpv.cpp
|
||||
InReadableOrder.cpp
|
||||
SpvBuilder.cpp
|
||||
SPVRemapper.cpp
|
||||
doc.cpp
|
||||
|
||||
@@ -1911,6 +1911,14 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate
|
||||
void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments)
|
||||
{
|
||||
const glslang::TIntermSequence& glslangArguments = node.getSequence();
|
||||
|
||||
glslang::TSampler sampler = {};
|
||||
bool cubeCompare = false;
|
||||
if (node.isTexture()) {
|
||||
sampler = glslangArguments[0]->getAsTyped()->getType().getSampler();
|
||||
cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)glslangArguments.size(); ++i) {
|
||||
builder.clearAccessChain();
|
||||
glslangArguments[i]->traverse(this);
|
||||
@@ -1929,6 +1937,51 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
|
||||
if (i == 0)
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTexture:
|
||||
if ((cubeCompare && i == 3) || (! cubeCompare && i == 2))
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTextureClamp:
|
||||
if ((cubeCompare && i == 4) || (! cubeCompare && i == 3))
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTextureLod:
|
||||
case glslang::EOpSparseTextureOffset:
|
||||
if (i == 3)
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTextureFetch:
|
||||
if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2))
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTextureFetchOffset:
|
||||
if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3))
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTextureLodOffset:
|
||||
case glslang::EOpSparseTextureGrad:
|
||||
case glslang::EOpSparseTextureOffsetClamp:
|
||||
if (i == 4)
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTextureGradOffset:
|
||||
case glslang::EOpSparseTextureGradClamp:
|
||||
if (i == 5)
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTextureGradOffsetClamp:
|
||||
if (i == 6)
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTextureGather:
|
||||
if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2))
|
||||
lvalue = true;
|
||||
break;
|
||||
case glslang::EOpSparseTextureGatherOffset:
|
||||
case glslang::EOpSparseTextureGatherOffsets:
|
||||
if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3))
|
||||
lvalue = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1990,6 +2043,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
||||
return builder.createTextureQueryCall(spv::OpImageQueryLod, params);
|
||||
case glslang::EOpTextureQueryLevels:
|
||||
return builder.createTextureQueryCall(spv::OpImageQueryLevels, params);
|
||||
case glslang::EOpSparseTexelsResident:
|
||||
return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]);
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
@@ -2017,7 +2072,11 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
||||
operands.push_back(*opIt);
|
||||
builder.createNoResultOp(spv::OpImageWrite, operands);
|
||||
return spv::NoResult;
|
||||
} else {
|
||||
} else if (node->isSparseImage()) {
|
||||
spv::MissingFunctionality("sparse image functions");
|
||||
return spv::NoResult;
|
||||
}
|
||||
else {
|
||||
// Process image atomic operations
|
||||
|
||||
// GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer,
|
||||
@@ -2037,7 +2096,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
||||
}
|
||||
|
||||
// Check for texture functions other than queries
|
||||
|
||||
bool sparse = node->isSparseTexture();
|
||||
bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
|
||||
|
||||
// check for bias argument
|
||||
@@ -2048,6 +2107,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
||||
++nonBiasArgCount;
|
||||
if (cracked.grad)
|
||||
nonBiasArgCount += 2;
|
||||
if (cracked.lodClamp)
|
||||
++nonBiasArgCount;
|
||||
if (sparse)
|
||||
++nonBiasArgCount;
|
||||
|
||||
if ((int)arguments.size() > nonBiasArgCount)
|
||||
bias = true;
|
||||
@@ -2059,9 +2122,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
||||
int extraArgs = 0;
|
||||
|
||||
// sort out where Dref is coming from
|
||||
if (sampler.shadow && sampler.dim == glslang::EsdCube && sampler.arrayed)
|
||||
if (cubeCompare) {
|
||||
params.Dref = arguments[2];
|
||||
else if (sampler.shadow && cracked.gather) {
|
||||
++extraArgs;
|
||||
} else if (sampler.shadow && cracked.gather) {
|
||||
params.Dref = arguments[2];
|
||||
++extraArgs;
|
||||
} else if (sampler.shadow) {
|
||||
@@ -2093,6 +2157,14 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
||||
params.offsets = arguments[2 + extraArgs];
|
||||
++extraArgs;
|
||||
}
|
||||
if (cracked.lodClamp) {
|
||||
params.lodClamp = arguments[2 + extraArgs];
|
||||
++extraArgs;
|
||||
}
|
||||
if (sparse) {
|
||||
params.texelOut = arguments[2 + extraArgs];
|
||||
++extraArgs;
|
||||
}
|
||||
if (bias) {
|
||||
params.bias = arguments[2 + extraArgs];
|
||||
++extraArgs;
|
||||
@@ -2107,7 +2179,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
||||
}
|
||||
}
|
||||
|
||||
return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), cracked.fetch, cracked.proj, cracked.gather, params);
|
||||
return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), sparse, cracked.fetch, cracked.proj, cracked.gather, params);
|
||||
}
|
||||
|
||||
spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)
|
||||
@@ -2981,7 +3053,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
|
||||
|
||||
spv::Op opCode = spv::OpNop;
|
||||
int libCall = -1;
|
||||
int consumedOperands = operands.size();
|
||||
size_t consumedOperands = operands.size();
|
||||
spv::Id typeId0 = 0;
|
||||
if (consumedOperands > 0)
|
||||
typeId0 = builder.getTypeId(operands[0]);
|
||||
|
||||
104
SPIRV/InReadableOrder.cpp
Normal file
104
SPIRV/InReadableOrder.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
//
|
||||
//Copyright (C) 2016 Google, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Author: Dejan Mircevski, Google
|
||||
//
|
||||
|
||||
// The SPIR-V spec requires code blocks to appear in an order satisfying the
|
||||
// dominator-tree direction (ie, dominator before the dominated). This is,
|
||||
// actually, easy to achieve: any pre-order CFG traversal algorithm will do it.
|
||||
// Because such algorithms visit a block only after traversing some path to it
|
||||
// from the root, they necessarily visit the block's idom first.
|
||||
//
|
||||
// But not every graph-traversal algorithm outputs blocks in an order that
|
||||
// appears logical to human readers. The problem is that unrelated branches may
|
||||
// be interspersed with each other, and merge blocks may come before some of the
|
||||
// branches being merged.
|
||||
//
|
||||
// A good, human-readable order of blocks may be achieved by performing
|
||||
// depth-first search but delaying merge nodes until after all their branches
|
||||
// have been visited. This is implemented below by the inReadableOrder()
|
||||
// function.
|
||||
|
||||
#include "spvIR.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <unordered_map>
|
||||
|
||||
using spv::Block;
|
||||
using spv::Id;
|
||||
|
||||
namespace {
|
||||
// Traverses CFG in a readable order, invoking a pre-set callback on each block.
|
||||
// Use by calling visit() on the root block.
|
||||
class ReadableOrderTraverser {
|
||||
public:
|
||||
explicit ReadableOrderTraverser(std::function<void(Block*)> callback) : callback_(callback) {}
|
||||
// Visits the block if it hasn't been visited already and isn't currently
|
||||
// being delayed. Invokes callback(block), then descends into its successors.
|
||||
// Delays merge-block processing until all the branches have been completed.
|
||||
void visit(Block* block)
|
||||
{
|
||||
assert(block);
|
||||
if (visited_[block] || delayed_[block])
|
||||
return;
|
||||
callback_(block);
|
||||
visited_[block] = true;
|
||||
Block* mergeBlock = nullptr;
|
||||
auto mergeInst = block->getMergeInstruction();
|
||||
if (mergeInst) {
|
||||
Id mergeId = mergeInst->getIdOperand(0);
|
||||
mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock();
|
||||
delayed_[mergeBlock] = true;
|
||||
}
|
||||
for (const auto succ : block->getSuccessors())
|
||||
visit(succ);
|
||||
if (mergeBlock) {
|
||||
delayed_[mergeBlock] = false;
|
||||
visit(mergeBlock);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void(Block*)> callback_;
|
||||
// Whether a block has already been visited or is being delayed.
|
||||
std::unordered_map<Block *, bool> visited_, delayed_;
|
||||
};
|
||||
}
|
||||
|
||||
void spv::inReadableOrder(Block* root, std::function<void(Block*)> callback)
|
||||
{
|
||||
ReadableOrderTraverser(callback).visit(root);
|
||||
}
|
||||
@@ -77,7 +77,7 @@ Id Builder::import(const char* name)
|
||||
Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport);
|
||||
import->addStringOperand(name);
|
||||
|
||||
imports.push_back(import);
|
||||
imports.push_back(std::unique_ptr<Instruction>(import));
|
||||
return import->getResultId();
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ Id Builder::makeVoidType()
|
||||
if (groupedTypes[OpTypeVoid].size() == 0) {
|
||||
type = new Instruction(getUniqueId(), NoType, OpTypeVoid);
|
||||
groupedTypes[OpTypeVoid].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
} else
|
||||
type = groupedTypes[OpTypeVoid].back();
|
||||
@@ -102,7 +102,7 @@ Id Builder::makeBoolType()
|
||||
if (groupedTypes[OpTypeBool].size() == 0) {
|
||||
type = new Instruction(getUniqueId(), NoType, OpTypeBool);
|
||||
groupedTypes[OpTypeBool].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
} else
|
||||
type = groupedTypes[OpTypeBool].back();
|
||||
@@ -116,7 +116,7 @@ Id Builder::makeSamplerType()
|
||||
if (groupedTypes[OpTypeSampler].size() == 0) {
|
||||
type = new Instruction(getUniqueId(), NoType, OpTypeSampler);
|
||||
groupedTypes[OpTypeSampler].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
} else
|
||||
type = groupedTypes[OpTypeSampler].back();
|
||||
@@ -140,7 +140,7 @@ Id Builder::makePointer(StorageClass storageClass, Id pointee)
|
||||
type->addImmediateOperand(storageClass);
|
||||
type->addIdOperand(pointee);
|
||||
groupedTypes[OpTypePointer].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -162,7 +162,7 @@ Id Builder::makeIntegerType(int width, bool hasSign)
|
||||
type->addImmediateOperand(width);
|
||||
type->addImmediateOperand(hasSign ? 1 : 0);
|
||||
groupedTypes[OpTypeInt].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -182,7 +182,7 @@ Id Builder::makeFloatType(int width)
|
||||
type = new Instruction(getUniqueId(), NoType, OpTypeFloat);
|
||||
type->addImmediateOperand(width);
|
||||
groupedTypes[OpTypeFloat].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -202,7 +202,7 @@ Id Builder::makeStructType(std::vector<Id>& members, const char* name)
|
||||
for (int op = 0; op < (int)members.size(); ++op)
|
||||
type->addIdOperand(members[op]);
|
||||
groupedTypes[OpTypeStruct].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
addName(type->getResultId(), name);
|
||||
|
||||
@@ -249,7 +249,7 @@ Id Builder::makeVectorType(Id component, int size)
|
||||
type->addIdOperand(component);
|
||||
type->addImmediateOperand(size);
|
||||
groupedTypes[OpTypeVector].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -275,7 +275,7 @@ Id Builder::makeMatrixType(Id component, int cols, int rows)
|
||||
type->addIdOperand(column);
|
||||
type->addImmediateOperand(cols);
|
||||
groupedTypes[OpTypeMatrix].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -305,7 +305,7 @@ Id Builder::makeArrayType(Id element, unsigned size, int stride)
|
||||
type->addIdOperand(element);
|
||||
type->addIdOperand(sizeId);
|
||||
groupedTypes[OpTypeArray].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -315,7 +315,7 @@ Id Builder::makeRuntimeArray(Id element)
|
||||
{
|
||||
Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray);
|
||||
type->addIdOperand(element);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -346,7 +346,7 @@ Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
|
||||
for (int p = 0; p < (int)paramTypes.size(); ++p)
|
||||
type->addIdOperand(paramTypes[p]);
|
||||
groupedTypes[OpTypeFunction].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -379,7 +379,7 @@ Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, boo
|
||||
type->addImmediateOperand((unsigned int)format);
|
||||
|
||||
groupedTypes[OpTypeImage].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -400,7 +400,7 @@ Id Builder::makeSampledImageType(Id imageType)
|
||||
type->addIdOperand(imageType);
|
||||
|
||||
groupedTypes[OpTypeSampledImage].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
@@ -594,7 +594,7 @@ Id Builder::makeBoolConstant(bool b, bool specConstant)
|
||||
|
||||
// Make it
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
constantsTypesGlobals.push_back(c);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
|
||||
groupedConstants[OpTypeBool].push_back(c);
|
||||
module.mapInstruction(c);
|
||||
|
||||
@@ -610,7 +610,7 @@ Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant)
|
||||
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
c->addImmediateOperand(value);
|
||||
constantsTypesGlobals.push_back(c);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
|
||||
groupedConstants[OpTypeInt].push_back(c);
|
||||
module.mapInstruction(c);
|
||||
|
||||
@@ -628,7 +628,7 @@ Id Builder::makeFloatConstant(float f, bool specConstant)
|
||||
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
c->addImmediateOperand(value);
|
||||
constantsTypesGlobals.push_back(c);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
|
||||
groupedConstants[OpTypeFloat].push_back(c);
|
||||
module.mapInstruction(c);
|
||||
|
||||
@@ -649,7 +649,7 @@ Id Builder::makeDoubleConstant(double d, bool specConstant)
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
c->addImmediateOperand(op1);
|
||||
c->addImmediateOperand(op2);
|
||||
constantsTypesGlobals.push_back(c);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
|
||||
groupedConstants[OpTypeFloat].push_back(c);
|
||||
module.mapInstruction(c);
|
||||
|
||||
@@ -708,7 +708,7 @@ Id Builder::makeCompositeConstant(Id typeId, std::vector<Id>& members)
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantComposite);
|
||||
for (int op = 0; op < (int)members.size(); ++op)
|
||||
c->addIdOperand(members[op]);
|
||||
constantsTypesGlobals.push_back(c);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
|
||||
groupedConstants[typeClass].push_back(c);
|
||||
module.mapInstruction(c);
|
||||
|
||||
@@ -722,7 +722,7 @@ Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, co
|
||||
entryPoint->addIdOperand(function->getId());
|
||||
entryPoint->addStringOperand(name);
|
||||
|
||||
entryPoints.push_back(entryPoint);
|
||||
entryPoints.push_back(std::unique_ptr<Instruction>(entryPoint));
|
||||
|
||||
return entryPoint;
|
||||
}
|
||||
@@ -740,7 +740,7 @@ void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int val
|
||||
if (value3 >= 0)
|
||||
instr->addImmediateOperand(value3);
|
||||
|
||||
executionModes.push_back(instr);
|
||||
executionModes.push_back(std::unique_ptr<Instruction>(instr));
|
||||
}
|
||||
|
||||
void Builder::addName(Id id, const char* string)
|
||||
@@ -749,7 +749,7 @@ void Builder::addName(Id id, const char* string)
|
||||
name->addIdOperand(id);
|
||||
name->addStringOperand(string);
|
||||
|
||||
names.push_back(name);
|
||||
names.push_back(std::unique_ptr<Instruction>(name));
|
||||
}
|
||||
|
||||
void Builder::addMemberName(Id id, int memberNumber, const char* string)
|
||||
@@ -759,7 +759,7 @@ void Builder::addMemberName(Id id, int memberNumber, const char* string)
|
||||
name->addImmediateOperand(memberNumber);
|
||||
name->addStringOperand(string);
|
||||
|
||||
names.push_back(name);
|
||||
names.push_back(std::unique_ptr<Instruction>(name));
|
||||
}
|
||||
|
||||
void Builder::addLine(Id target, Id fileName, int lineNum, int column)
|
||||
@@ -770,7 +770,7 @@ void Builder::addLine(Id target, Id fileName, int lineNum, int column)
|
||||
line->addImmediateOperand(lineNum);
|
||||
line->addImmediateOperand(column);
|
||||
|
||||
lines.push_back(line);
|
||||
lines.push_back(std::unique_ptr<Instruction>(line));
|
||||
}
|
||||
|
||||
void Builder::addDecoration(Id id, Decoration decoration, int num)
|
||||
@@ -783,7 +783,7 @@ void Builder::addDecoration(Id id, Decoration decoration, int num)
|
||||
if (num >= 0)
|
||||
dec->addImmediateOperand(num);
|
||||
|
||||
decorations.push_back(dec);
|
||||
decorations.push_back(std::unique_ptr<Instruction>(dec));
|
||||
}
|
||||
|
||||
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
|
||||
@@ -795,7 +795,7 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
|
||||
if (num >= 0)
|
||||
dec->addImmediateOperand(num);
|
||||
|
||||
decorations.push_back(dec);
|
||||
decorations.push_back(std::unique_ptr<Instruction>(dec));
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
@@ -827,6 +827,8 @@ Function* Builder::makeFunctionEntry(Id returnType, const char* name, std::vecto
|
||||
if (name)
|
||||
addName(function->getId(), name);
|
||||
|
||||
functions.push_back(std::unique_ptr<Function>(function));
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
@@ -836,9 +838,9 @@ void Builder::makeReturn(bool implicit, Id retVal)
|
||||
if (retVal) {
|
||||
Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue);
|
||||
inst->addIdOperand(retVal);
|
||||
buildPoint->addInstruction(inst);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
|
||||
} else
|
||||
buildPoint->addInstruction(new Instruction(NoResult, NoType, OpReturn));
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(NoResult, NoType, OpReturn)));
|
||||
|
||||
if (! implicit)
|
||||
createAndSetNoPredecessorBlock("post-return");
|
||||
@@ -855,7 +857,7 @@ void Builder::leaveFunction()
|
||||
if (! block->isTerminated()) {
|
||||
|
||||
// Whether we're in an unreachable (non-entry) block.
|
||||
bool unreachable = function.getEntryBlock() != block && block->getNumPredecessors() == 0;
|
||||
bool unreachable = function.getEntryBlock() != block && block->getPredecessors().empty();
|
||||
|
||||
if (unreachable) {
|
||||
// Given that this block is at the end of a function, it must be right after an
|
||||
@@ -878,7 +880,7 @@ void Builder::leaveFunction()
|
||||
// Comments in header
|
||||
void Builder::makeDiscard()
|
||||
{
|
||||
buildPoint->addInstruction(new Instruction(OpKill));
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(OpKill)));
|
||||
createAndSetNoPredecessorBlock("post-discard");
|
||||
}
|
||||
|
||||
@@ -892,11 +894,11 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
|
||||
switch (storageClass) {
|
||||
case StorageClassFunction:
|
||||
// Validation rules require the declaration in the entry block
|
||||
buildPoint->getParent().addLocalVariable(inst);
|
||||
buildPoint->getParent().addLocalVariable(std::unique_ptr<Instruction>(inst));
|
||||
break;
|
||||
|
||||
default:
|
||||
constantsTypesGlobals.push_back(inst);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
|
||||
module.mapInstruction(inst);
|
||||
break;
|
||||
}
|
||||
@@ -911,7 +913,7 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
|
||||
Id Builder::createUndefined(Id type)
|
||||
{
|
||||
Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
|
||||
buildPoint->addInstruction(inst);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
|
||||
return inst->getResultId();
|
||||
}
|
||||
|
||||
@@ -921,7 +923,7 @@ void Builder::createStore(Id rValue, Id lValue)
|
||||
Instruction* store = new Instruction(OpStore);
|
||||
store->addIdOperand(lValue);
|
||||
store->addIdOperand(rValue);
|
||||
buildPoint->addInstruction(store);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(store));
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
@@ -929,7 +931,7 @@ Id Builder::createLoad(Id lValue)
|
||||
{
|
||||
Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
|
||||
load->addIdOperand(lValue);
|
||||
buildPoint->addInstruction(load);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
|
||||
|
||||
return load->getResultId();
|
||||
}
|
||||
@@ -955,7 +957,7 @@ Id Builder::createAccessChain(StorageClass storageClass, Id base, std::vector<Id
|
||||
chain->addIdOperand(base);
|
||||
for (int i = 0; i < (int)offsets.size(); ++i)
|
||||
chain->addIdOperand(offsets[i]);
|
||||
buildPoint->addInstruction(chain);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(chain));
|
||||
|
||||
return chain->getResultId();
|
||||
}
|
||||
@@ -965,7 +967,7 @@ Id Builder::createArrayLength(Id base, unsigned int member)
|
||||
Instruction* length = new Instruction(getUniqueId(), makeIntType(32), OpArrayLength);
|
||||
length->addIdOperand(base);
|
||||
length->addImmediateOperand(member);
|
||||
buildPoint->addInstruction(length);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(length));
|
||||
|
||||
return length->getResultId();
|
||||
}
|
||||
@@ -975,7 +977,7 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
|
||||
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
|
||||
extract->addIdOperand(composite);
|
||||
extract->addImmediateOperand(index);
|
||||
buildPoint->addInstruction(extract);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
|
||||
|
||||
return extract->getResultId();
|
||||
}
|
||||
@@ -986,7 +988,7 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, std::vector<unsigned
|
||||
extract->addIdOperand(composite);
|
||||
for (int i = 0; i < (int)indexes.size(); ++i)
|
||||
extract->addImmediateOperand(indexes[i]);
|
||||
buildPoint->addInstruction(extract);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
|
||||
|
||||
return extract->getResultId();
|
||||
}
|
||||
@@ -997,7 +999,7 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned i
|
||||
insert->addIdOperand(object);
|
||||
insert->addIdOperand(composite);
|
||||
insert->addImmediateOperand(index);
|
||||
buildPoint->addInstruction(insert);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
|
||||
|
||||
return insert->getResultId();
|
||||
}
|
||||
@@ -1009,7 +1011,7 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, std::vecto
|
||||
insert->addIdOperand(composite);
|
||||
for (int i = 0; i < (int)indexes.size(); ++i)
|
||||
insert->addImmediateOperand(indexes[i]);
|
||||
buildPoint->addInstruction(insert);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
|
||||
|
||||
return insert->getResultId();
|
||||
}
|
||||
@@ -1019,7 +1021,7 @@ Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
|
||||
Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
|
||||
extract->addIdOperand(vector);
|
||||
extract->addIdOperand(componentIndex);
|
||||
buildPoint->addInstruction(extract);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
|
||||
|
||||
return extract->getResultId();
|
||||
}
|
||||
@@ -1030,7 +1032,7 @@ Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id com
|
||||
insert->addIdOperand(vector);
|
||||
insert->addIdOperand(component);
|
||||
insert->addIdOperand(componentIndex);
|
||||
buildPoint->addInstruction(insert);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
|
||||
|
||||
return insert->getResultId();
|
||||
}
|
||||
@@ -1039,7 +1041,7 @@ Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id com
|
||||
void Builder::createNoResultOp(Op opCode)
|
||||
{
|
||||
Instruction* op = new Instruction(opCode);
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
}
|
||||
|
||||
// An opcode that has one operand, no result id, and no type
|
||||
@@ -1047,7 +1049,7 @@ void Builder::createNoResultOp(Op opCode, Id operand)
|
||||
{
|
||||
Instruction* op = new Instruction(opCode);
|
||||
op->addIdOperand(operand);
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
}
|
||||
|
||||
// An opcode that has one operand, no result id, and no type
|
||||
@@ -1056,7 +1058,7 @@ void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands)
|
||||
Instruction* op = new Instruction(opCode);
|
||||
for (auto operand : operands)
|
||||
op->addIdOperand(operand);
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
}
|
||||
|
||||
void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
|
||||
@@ -1065,7 +1067,7 @@ void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemantic
|
||||
op->addImmediateOperand(makeUintConstant(execution));
|
||||
op->addImmediateOperand(makeUintConstant(memory));
|
||||
op->addImmediateOperand(makeUintConstant(semantics));
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
}
|
||||
|
||||
void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
|
||||
@@ -1073,7 +1075,7 @@ void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemant
|
||||
Instruction* op = new Instruction(OpMemoryBarrier);
|
||||
op->addImmediateOperand(makeUintConstant(executionScope));
|
||||
op->addImmediateOperand(makeUintConstant(memorySemantics));
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
}
|
||||
|
||||
// An opcode that has one operands, a result id, and a type
|
||||
@@ -1081,7 +1083,7 @@ Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
|
||||
{
|
||||
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
||||
op->addIdOperand(operand);
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
|
||||
return op->getResultId();
|
||||
}
|
||||
@@ -1091,7 +1093,7 @@ Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
|
||||
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
||||
op->addIdOperand(left);
|
||||
op->addIdOperand(right);
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
|
||||
return op->getResultId();
|
||||
}
|
||||
@@ -1102,7 +1104,7 @@ Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
|
||||
op->addIdOperand(op1);
|
||||
op->addIdOperand(op2);
|
||||
op->addIdOperand(op3);
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
|
||||
return op->getResultId();
|
||||
}
|
||||
@@ -1112,7 +1114,7 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
|
||||
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
||||
for (auto operand : operands)
|
||||
op->addIdOperand(operand);
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
|
||||
return op->getResultId();
|
||||
}
|
||||
@@ -1123,7 +1125,7 @@ Id Builder::createFunctionCall(spv::Function* function, std::vector<spv::Id>& ar
|
||||
op->addIdOperand(function->getId());
|
||||
for (int a = 0; a < (int)args.size(); ++a)
|
||||
op->addIdOperand(args[a]);
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
|
||||
return op->getResultId();
|
||||
}
|
||||
@@ -1140,7 +1142,7 @@ Id Builder::createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& cha
|
||||
swizzle->addIdOperand(source);
|
||||
for (int i = 0; i < (int)channels.size(); ++i)
|
||||
swizzle->addImmediateOperand(channels[i]);
|
||||
buildPoint->addInstruction(swizzle);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
|
||||
|
||||
return swizzle->getResultId();
|
||||
}
|
||||
@@ -1171,7 +1173,7 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<uns
|
||||
// finish the instruction with these components selectors
|
||||
for (int i = 0; i < numTargetComponents; ++i)
|
||||
swizzle->addImmediateOperand(components[i]);
|
||||
buildPoint->addInstruction(swizzle);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
|
||||
|
||||
return swizzle->getResultId();
|
||||
}
|
||||
@@ -1202,7 +1204,7 @@ Id Builder::smearScalar(Decoration /*precision*/, Id scalar, Id vectorType)
|
||||
Instruction* smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
|
||||
for (int c = 0; c < numComponents; ++c)
|
||||
smear->addIdOperand(scalar);
|
||||
buildPoint->addInstruction(smear);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(smear));
|
||||
|
||||
return smear->getResultId();
|
||||
}
|
||||
@@ -1216,13 +1218,13 @@ Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builti
|
||||
for (int arg = 0; arg < (int)args.size(); ++arg)
|
||||
inst->addIdOperand(args[arg]);
|
||||
|
||||
buildPoint->addInstruction(inst);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
|
||||
return inst->getResultId();
|
||||
}
|
||||
|
||||
// Accept all parameters needed to create a texture instruction.
|
||||
// Create the correct instruction based on the inputs, and make the call.
|
||||
Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, bool gather, const TextureParameters& parameters)
|
||||
Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, const TextureParameters& parameters)
|
||||
{
|
||||
static const int maxTextureArgs = 10;
|
||||
Id texArgs[maxTextureArgs] = {};
|
||||
@@ -1275,6 +1277,10 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
|
||||
mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask);
|
||||
texArgs[numArgs++] = parameters.sample;
|
||||
}
|
||||
if (parameters.lodClamp) {
|
||||
mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask);
|
||||
texArgs[numArgs++] = parameters.lodClamp;
|
||||
}
|
||||
if (mask == ImageOperandsMaskNone)
|
||||
--numArgs; // undo speculative reservation for the mask argument
|
||||
else
|
||||
@@ -1286,35 +1292,68 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
|
||||
Op opCode;
|
||||
opCode = OpImageSampleImplicitLod;
|
||||
if (fetch) {
|
||||
opCode = OpImageFetch;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseFetch;
|
||||
else
|
||||
opCode = OpImageFetch;
|
||||
} else if (gather) {
|
||||
if (parameters.Dref)
|
||||
opCode = OpImageDrefGather;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseDrefGather;
|
||||
else
|
||||
opCode = OpImageDrefGather;
|
||||
else
|
||||
opCode = OpImageGather;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseGather;
|
||||
else
|
||||
opCode = OpImageGather;
|
||||
} else if (xplicit) {
|
||||
if (parameters.Dref) {
|
||||
if (proj)
|
||||
opCode = OpImageSampleProjDrefExplicitLod;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseSampleProjDrefExplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleProjDrefExplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleDrefExplicitLod;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseSampleDrefExplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleDrefExplicitLod;
|
||||
} else {
|
||||
if (proj)
|
||||
opCode = OpImageSampleProjExplicitLod;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseSampleProjExplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleProjExplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleExplicitLod;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseSampleExplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleExplicitLod;
|
||||
}
|
||||
} else {
|
||||
if (parameters.Dref) {
|
||||
if (proj)
|
||||
opCode = OpImageSampleProjDrefImplicitLod;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseSampleProjDrefImplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleProjDrefImplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleDrefImplicitLod;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseSampleDrefImplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleDrefImplicitLod;
|
||||
} else {
|
||||
if (proj)
|
||||
opCode = OpImageSampleProjImplicitLod;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseSampleProjImplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleProjImplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleImplicitLod;
|
||||
if (sparse)
|
||||
opCode = OpImageSparseSampleImplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleImplicitLod;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1335,6 +1374,15 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
|
||||
}
|
||||
}
|
||||
|
||||
Id typeId0 = 0;
|
||||
Id typeId1 = 0;
|
||||
|
||||
if (sparse) {
|
||||
typeId0 = resultType;
|
||||
typeId1 = getDerefTypeId(parameters.texelOut);
|
||||
resultType = makeStructResultType(typeId0, typeId1);
|
||||
}
|
||||
|
||||
// Build the SPIR-V instruction
|
||||
Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode);
|
||||
for (int op = 0; op < optArgNum; ++op)
|
||||
@@ -1344,14 +1392,20 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
|
||||
for (int op = optArgNum + 1; op < numArgs; ++op)
|
||||
textureInst->addIdOperand(texArgs[op]);
|
||||
setPrecision(textureInst->getResultId(), precision);
|
||||
buildPoint->addInstruction(textureInst);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(textureInst));
|
||||
|
||||
Id resultId = textureInst->getResultId();
|
||||
|
||||
// When a smear is needed, do it, as per what was computed
|
||||
// above when resultType was changed to a scalar type.
|
||||
if (resultType != smearedType)
|
||||
resultId = smearScalar(precision, resultId, smearedType);
|
||||
if (sparse) {
|
||||
// Decode the return type that was a special structure
|
||||
createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut);
|
||||
resultId = createCompositeExtract(resultId, typeId0, 0);
|
||||
} else {
|
||||
// When a smear is needed, do it, as per what was computed
|
||||
// above when resultType was changed to a scalar type.
|
||||
if (resultType != smearedType)
|
||||
resultId = smearScalar(precision, resultId, smearedType);
|
||||
}
|
||||
|
||||
return resultId;
|
||||
}
|
||||
@@ -1365,7 +1419,7 @@ Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameter
|
||||
case OpImageQuerySize:
|
||||
case OpImageQuerySizeLod:
|
||||
{
|
||||
int numComponents;
|
||||
int numComponents = 0;
|
||||
switch (getTypeDimensionality(getImageType(parameters.sampler))) {
|
||||
case Dim1D:
|
||||
case DimBuffer:
|
||||
@@ -1412,7 +1466,7 @@ Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameter
|
||||
query->addIdOperand(parameters.coords);
|
||||
if (parameters.lod)
|
||||
query->addIdOperand(parameters.lod);
|
||||
buildPoint->addInstruction(query);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(query));
|
||||
|
||||
return query->getResultId();
|
||||
}
|
||||
@@ -1494,7 +1548,7 @@ Id Builder::createCompositeConstruct(Id typeId, std::vector<Id>& constituents)
|
||||
Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
|
||||
for (int c = 0; c < (int)constituents.size(); ++c)
|
||||
op->addIdOperand(constituents[c]);
|
||||
buildPoint->addInstruction(op);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
|
||||
|
||||
return op->getResultId();
|
||||
}
|
||||
@@ -1705,12 +1759,15 @@ void Builder::makeSwitch(Id selector, int numSegments, std::vector<int>& caseVal
|
||||
// make the switch instruction
|
||||
Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
|
||||
switchInst->addIdOperand(selector);
|
||||
switchInst->addIdOperand(defaultSegment >= 0 ? segmentBlocks[defaultSegment]->getId() : mergeBlock->getId());
|
||||
auto defaultOrMerge = (defaultSegment >= 0) ? segmentBlocks[defaultSegment] : mergeBlock;
|
||||
switchInst->addIdOperand(defaultOrMerge->getId());
|
||||
defaultOrMerge->addPredecessor(buildPoint);
|
||||
for (int i = 0; i < (int)caseValues.size(); ++i) {
|
||||
switchInst->addImmediateOperand(caseValues[i]);
|
||||
switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId());
|
||||
segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint);
|
||||
}
|
||||
buildPoint->addInstruction(switchInst);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(switchInst));
|
||||
|
||||
// push the merge block
|
||||
switchMerges.push(mergeBlock);
|
||||
@@ -2092,7 +2149,7 @@ void Builder::createBranch(Block* block)
|
||||
{
|
||||
Instruction* branch = new Instruction(OpBranch);
|
||||
branch->addIdOperand(block->getId());
|
||||
buildPoint->addInstruction(branch);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
|
||||
block->addPredecessor(buildPoint);
|
||||
}
|
||||
|
||||
@@ -2101,7 +2158,7 @@ void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
|
||||
Instruction* merge = new Instruction(OpSelectionMerge);
|
||||
merge->addIdOperand(mergeBlock->getId());
|
||||
merge->addImmediateOperand(control);
|
||||
buildPoint->addInstruction(merge);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
|
||||
}
|
||||
|
||||
void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control)
|
||||
@@ -2110,7 +2167,7 @@ void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned
|
||||
merge->addIdOperand(mergeBlock->getId());
|
||||
merge->addIdOperand(continueBlock->getId());
|
||||
merge->addImmediateOperand(control);
|
||||
buildPoint->addInstruction(merge);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
|
||||
}
|
||||
|
||||
void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
|
||||
@@ -2119,12 +2176,12 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els
|
||||
branch->addIdOperand(condition);
|
||||
branch->addIdOperand(thenBlock->getId());
|
||||
branch->addIdOperand(elseBlock->getId());
|
||||
buildPoint->addInstruction(branch);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
|
||||
thenBlock->addPredecessor(buildPoint);
|
||||
elseBlock->addPredecessor(buildPoint);
|
||||
}
|
||||
|
||||
void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<Instruction*>& instructions) const
|
||||
void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
|
||||
{
|
||||
for (int i = 0; i < (int)instructions.size(); ++i) {
|
||||
instructions[i]->dump(out);
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "spvIR.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
@@ -201,11 +202,13 @@ public:
|
||||
void setBuildPoint(Block* bp) { buildPoint = bp; }
|
||||
Block* getBuildPoint() const { return buildPoint; }
|
||||
|
||||
// Make the main function.
|
||||
// Make the main function. The returned pointer is only valid
|
||||
// for the lifetime of this builder.
|
||||
Function* makeMain();
|
||||
|
||||
// Make a shader-style function, and create its entry block if entry is non-zero.
|
||||
// Return the function, pass back the entry.
|
||||
// The returned pointer is only valid for the lifetime of this builder.
|
||||
Function* makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry = 0);
|
||||
|
||||
// Create a return. An 'implicit' return is one not appearing in the source
|
||||
@@ -310,10 +313,12 @@ public:
|
||||
Id gradY;
|
||||
Id sample;
|
||||
Id comp;
|
||||
Id texelOut;
|
||||
Id lodClamp;
|
||||
};
|
||||
|
||||
// Select the correct texture operation based on all inputs, and emit the correct instruction
|
||||
Id createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, bool gather, const TextureParameters&);
|
||||
Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, const TextureParameters&);
|
||||
|
||||
// Emit the OpTextureQuery* instruction that was passed in.
|
||||
// Figure out the right return value and type, and return it.
|
||||
@@ -513,7 +518,7 @@ public:
|
||||
void simplifyAccessChainSwizzle();
|
||||
void createAndSetNoPredecessorBlock(const char*);
|
||||
void createSelectionMerge(Block* mergeBlock, unsigned int control);
|
||||
void dumpInstructions(std::vector<unsigned int>&, const std::vector<Instruction*>&) const;
|
||||
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
|
||||
|
||||
SourceLanguage source;
|
||||
int sourceVersion;
|
||||
@@ -529,14 +534,15 @@ public:
|
||||
AccessChain accessChain;
|
||||
|
||||
// special blocks of instructions for output
|
||||
std::vector<Instruction*> imports;
|
||||
std::vector<Instruction*> entryPoints;
|
||||
std::vector<Instruction*> executionModes;
|
||||
std::vector<Instruction*> names;
|
||||
std::vector<Instruction*> lines;
|
||||
std::vector<Instruction*> decorations;
|
||||
std::vector<Instruction*> constantsTypesGlobals;
|
||||
std::vector<Instruction*> externals;
|
||||
std::vector<std::unique_ptr<Instruction> > imports;
|
||||
std::vector<std::unique_ptr<Instruction> > entryPoints;
|
||||
std::vector<std::unique_ptr<Instruction> > executionModes;
|
||||
std::vector<std::unique_ptr<Instruction> > names;
|
||||
std::vector<std::unique_ptr<Instruction> > lines;
|
||||
std::vector<std::unique_ptr<Instruction> > decorations;
|
||||
std::vector<std::unique_ptr<Instruction> > constantsTypesGlobals;
|
||||
std::vector<std::unique_ptr<Instruction> > externals;
|
||||
std::vector<std::unique_ptr<Function> > functions;
|
||||
|
||||
// not output, internally used for quick & dirty canonical (unique) creation
|
||||
std::vector<Instruction*> groupedConstants[OpConstant]; // all types appear before OpConstant
|
||||
|
||||
1756
SPIRV/spirv.hpp
1756
SPIRV/spirv.hpp
File diff suppressed because it is too large
Load Diff
@@ -53,12 +53,15 @@
|
||||
#include "spirv.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace spv {
|
||||
|
||||
class Block;
|
||||
class Function;
|
||||
class Module;
|
||||
|
||||
@@ -75,8 +78,8 @@ const MemorySemanticsMask MemorySemanticsAllMemory = (MemorySemanticsMask)0x3FF;
|
||||
|
||||
class Instruction {
|
||||
public:
|
||||
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode) { }
|
||||
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode) { }
|
||||
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { }
|
||||
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { }
|
||||
virtual ~Instruction() {}
|
||||
void addIdOperand(Id id) { operands.push_back(id); }
|
||||
void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); }
|
||||
@@ -107,6 +110,8 @@ public:
|
||||
addImmediateOperand(word);
|
||||
}
|
||||
}
|
||||
void setBlock(Block* b) { block = b; }
|
||||
Block* getBlock() const { return block; }
|
||||
Op getOpCode() const { return opCode; }
|
||||
int getNumOperands() const { return (int)operands.size(); }
|
||||
Id getResultId() const { return resultId; }
|
||||
@@ -145,6 +150,7 @@ protected:
|
||||
Op opCode;
|
||||
std::vector<Id> operands;
|
||||
std::string originalString; // could be optimized away; convenience for getting string operand
|
||||
Block* block;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -156,18 +162,31 @@ public:
|
||||
Block(Id id, Function& parent);
|
||||
virtual ~Block()
|
||||
{
|
||||
// TODO: free instructions
|
||||
}
|
||||
|
||||
|
||||
Id getId() { return instructions.front()->getResultId(); }
|
||||
|
||||
Function& getParent() const { return parent; }
|
||||
void addInstruction(Instruction* inst);
|
||||
void addPredecessor(Block* pred) { predecessors.push_back(pred); }
|
||||
void addLocalVariable(Instruction* inst) { localVariables.push_back(inst); }
|
||||
int getNumPredecessors() const { return (int)predecessors.size(); }
|
||||
void addInstruction(std::unique_ptr<Instruction> inst);
|
||||
void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);}
|
||||
void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
|
||||
const std::vector<Block*>& getPredecessors() const { return predecessors; }
|
||||
const std::vector<Block*>& getSuccessors() const { return successors; }
|
||||
void setUnreachable() { unreachable = true; }
|
||||
bool isUnreachable() const { return unreachable; }
|
||||
// Returns the block's merge instruction, if one exists (otherwise null).
|
||||
const Instruction* getMergeInstruction() const {
|
||||
if (instructions.size() < 2) return nullptr;
|
||||
const Instruction* nextToLast = (instructions.cend() - 2)->get();
|
||||
switch (nextToLast->getOpCode()) {
|
||||
case OpSelectionMerge:
|
||||
case OpLoopMerge:
|
||||
return nextToLast;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool isTerminated() const
|
||||
{
|
||||
@@ -206,9 +225,9 @@ protected:
|
||||
// To enforce keeping parent and ownership in sync:
|
||||
friend Function;
|
||||
|
||||
std::vector<Instruction*> instructions;
|
||||
std::vector<Block*> predecessors;
|
||||
std::vector<Instruction*> localVariables;
|
||||
std::vector<std::unique_ptr<Instruction> > instructions;
|
||||
std::vector<Block*> predecessors, successors;
|
||||
std::vector<std::unique_ptr<Instruction> > localVariables;
|
||||
Function& parent;
|
||||
|
||||
// track whether this block is known to be uncreachable (not necessarily
|
||||
@@ -217,6 +236,11 @@ protected:
|
||||
bool unreachable;
|
||||
};
|
||||
|
||||
// Traverses the control-flow graph rooted at root in an order suited for
|
||||
// readable code generation. Invokes callback at every node in the traversal
|
||||
// order.
|
||||
void inReadableOrder(Block* root, std::function<void(Block*)> callback);
|
||||
|
||||
//
|
||||
// SPIR-V IR Function.
|
||||
//
|
||||
@@ -247,7 +271,7 @@ public:
|
||||
Module& getParent() const { return parent; }
|
||||
Block* getEntryBlock() const { return blocks.front(); }
|
||||
Block* getLastBlock() const { return blocks.back(); }
|
||||
void addLocalVariable(Instruction* inst);
|
||||
void addLocalVariable(std::unique_ptr<Instruction> inst);
|
||||
Id getReturnType() const { return functionInstruction.getTypeId(); }
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
@@ -259,8 +283,7 @@ public:
|
||||
parameterInstructions[p]->dump(out);
|
||||
|
||||
// Blocks
|
||||
for (int b = 0; b < (int)blocks.size(); ++b)
|
||||
blocks[b]->dump(out);
|
||||
inReadableOrder(blocks[0], [&out](const Block* b) { b->dump(out); });
|
||||
Instruction end(0, 0, OpFunctionEnd);
|
||||
end.dump(out);
|
||||
}
|
||||
@@ -348,22 +371,27 @@ __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParam
|
||||
}
|
||||
}
|
||||
|
||||
__inline void Function::addLocalVariable(Instruction* inst)
|
||||
__inline void Function::addLocalVariable(std::unique_ptr<Instruction> inst)
|
||||
{
|
||||
blocks[0]->addLocalVariable(inst);
|
||||
parent.mapInstruction(inst);
|
||||
Instruction* raw_instruction = inst.get();
|
||||
blocks[0]->addLocalVariable(std::move(inst));
|
||||
parent.mapInstruction(raw_instruction);
|
||||
}
|
||||
|
||||
__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false)
|
||||
{
|
||||
instructions.push_back(new Instruction(id, NoType, OpLabel));
|
||||
instructions.push_back(std::unique_ptr<Instruction>(new Instruction(id, NoType, OpLabel)));
|
||||
instructions.back()->setBlock(this);
|
||||
parent.getParent().mapInstruction(instructions.back().get());
|
||||
}
|
||||
|
||||
__inline void Block::addInstruction(Instruction* inst)
|
||||
__inline void Block::addInstruction(std::unique_ptr<Instruction> inst)
|
||||
{
|
||||
instructions.push_back(inst);
|
||||
if (inst->getResultId())
|
||||
parent.getParent().mapInstruction(inst);
|
||||
Instruction* raw_instruction = inst.get();
|
||||
instructions.push_back(std::move(inst));
|
||||
raw_instruction->setBlock(this);
|
||||
if (raw_instruction->getResultId())
|
||||
parent.getParent().mapInstruction(raw_instruction);
|
||||
}
|
||||
|
||||
}; // end spv namespace
|
||||
|
||||
Reference in New Issue
Block a user