Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
glslang
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
glslang
Commits
e0bc65b2
Unverified
Commit
e0bc65b2
authored
Aug 06, 2018
by
John Kessenich
Committed by
GitHub
Aug 06, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1460 from KhronosGroup/postprocess
Non-Functional: Add postprocess as more robust way to add capabilities
parents
29619b23
f04c51b3
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
178 additions
and
54 deletions
+178
-54
CMakeLists.txt
SPIRV/CMakeLists.txt
+1
-0
GlslangToSpv.cpp
SPIRV/GlslangToSpv.cpp
+4
-12
SpvBuilder.cpp
SPIRV/SpvBuilder.cpp
+0
-39
SpvBuilder.h
SPIRV/SpvBuilder.h
+9
-3
SpvPostProcess.cpp
SPIRV/SpvPostProcess.cpp
+164
-0
No files found.
SPIRV/CMakeLists.txt
View file @
e0bc65b2
...
...
@@ -3,6 +3,7 @@ set(SOURCES
InReadableOrder.cpp
Logger.cpp
SpvBuilder.cpp
SpvPostProcess.cpp
doc.cpp
disassemble.cpp
)
...
...
SPIRV/GlslangToSpv.cpp
View file @
e0bc65b2
...
...
@@ -1191,6 +1191,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl
// Finish creating SPV, after the traversal is complete.
void
TGlslangToSpvTraverser
::
finishSpv
()
{
// Finish the entry point function
if
(
!
entryPointTerminated
)
{
builder
.
setBuildPoint
(
shaderEntry
->
getLastBlock
());
builder
.
leaveFunction
();
...
...
@@ -1200,7 +1201,9 @@ void TGlslangToSpvTraverser::finishSpv()
for
(
auto
it
=
iOSet
.
cbegin
();
it
!=
iOSet
.
cend
();
++
it
)
entryPoint
->
addIdOperand
(
*
it
);
builder
.
eliminateDeadDecorations
();
// Add capabilities, extensions, remove unneeded decorations, etc.,
// based on the resulting SPIR-V.
builder
.
postProcess
();
}
// Write the SPV into 'out'.
...
...
@@ -4627,27 +4630,21 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe
unaryOp
=
spv
::
OpFwidth
;
break
;
case
glslang
:
:
EOpDPdxFine
:
builder
.
addCapability
(
spv
::
CapabilityDerivativeControl
);
unaryOp
=
spv
::
OpDPdxFine
;
break
;
case
glslang
:
:
EOpDPdyFine
:
builder
.
addCapability
(
spv
::
CapabilityDerivativeControl
);
unaryOp
=
spv
::
OpDPdyFine
;
break
;
case
glslang
:
:
EOpFwidthFine
:
builder
.
addCapability
(
spv
::
CapabilityDerivativeControl
);
unaryOp
=
spv
::
OpFwidthFine
;
break
;
case
glslang
:
:
EOpDPdxCoarse
:
builder
.
addCapability
(
spv
::
CapabilityDerivativeControl
);
unaryOp
=
spv
::
OpDPdxCoarse
;
break
;
case
glslang
:
:
EOpDPdyCoarse
:
builder
.
addCapability
(
spv
::
CapabilityDerivativeControl
);
unaryOp
=
spv
::
OpDPdyCoarse
;
break
;
case
glslang
:
:
EOpFwidthCoarse
:
builder
.
addCapability
(
spv
::
CapabilityDerivativeControl
);
unaryOp
=
spv
::
OpFwidthCoarse
;
break
;
case
glslang
:
:
EOpInterpolateAtCentroid
:
...
...
@@ -4655,7 +4652,6 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe
if
(
typeProxy
==
glslang
::
EbtFloat16
)
builder
.
addExtension
(
spv
::
E_SPV_AMD_gpu_shader_half_float
);
#endif
builder
.
addCapability
(
spv
::
CapabilityInterpolationFunction
);
libCall
=
spv
::
GLSLstd450InterpolateAtCentroid
;
break
;
case
glslang
:
:
EOpAny
:
...
...
@@ -4791,8 +4787,6 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe
#endif
#ifdef NV_EXTENSIONS
case
glslang
:
:
EOpSubgroupPartition
:
builder
.
addExtension
(
spv
::
E_SPV_NV_shader_subgroup_partitioned
);
builder
.
addCapability
(
spv
::
CapabilityGroupNonUniformPartitionedNV
);
unaryOp
=
spv
::
OpGroupNonUniformPartitionNV
;
break
;
#endif
...
...
@@ -6087,7 +6081,6 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
if
(
typeProxy
==
glslang
::
EbtFloat16
)
builder
.
addExtension
(
spv
::
E_SPV_AMD_gpu_shader_half_float
);
#endif
builder
.
addCapability
(
spv
::
CapabilityInterpolationFunction
);
libCall
=
spv
::
GLSLstd450InterpolateAtSample
;
break
;
case
glslang
:
:
EOpInterpolateAtOffset
:
...
...
@@ -6095,7 +6088,6 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
if
(
typeProxy
==
glslang
::
EbtFloat16
)
builder
.
addExtension
(
spv
::
E_SPV_AMD_gpu_shader_half_float
);
#endif
builder
.
addCapability
(
spv
::
CapabilityInterpolationFunction
);
libCall
=
spv
::
GLSLstd450InterpolateAtOffset
;
break
;
case
glslang
:
:
EOpAddCarry
:
...
...
SPIRV/SpvBuilder.cpp
View file @
e0bc65b2
...
...
@@ -1774,9 +1774,6 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
// Comments in header
Id
Builder
::
createTextureQueryCall
(
Op
opCode
,
const
TextureParameters
&
parameters
,
bool
isUnsignedResult
)
{
// All these need a capability
addCapability
(
CapabilityImageQuery
);
// Figure out the result type
Id
resultType
=
0
;
switch
(
opCode
)
{
...
...
@@ -2483,42 +2480,6 @@ Id Builder::accessChainGetInferredType()
return
type
;
}
// comment in header
void
Builder
::
eliminateDeadDecorations
()
{
std
::
unordered_set
<
const
Block
*>
reachable_blocks
;
std
::
unordered_set
<
Id
>
unreachable_definitions
;
// Collect IDs defined in unreachable blocks. For each function, label the
// reachable blocks first. Then for each unreachable block, collect the
// result IDs of the instructions in it.
for
(
std
::
vector
<
Function
*>::
const_iterator
fi
=
module
.
getFunctions
().
cbegin
();
fi
!=
module
.
getFunctions
().
cend
();
fi
++
)
{
Function
*
f
=
*
fi
;
Block
*
entry
=
f
->
getEntryBlock
();
inReadableOrder
(
entry
,
[
&
reachable_blocks
](
const
Block
*
b
)
{
reachable_blocks
.
insert
(
b
);
});
for
(
std
::
vector
<
Block
*>::
const_iterator
bi
=
f
->
getBlocks
().
cbegin
();
bi
!=
f
->
getBlocks
().
cend
();
bi
++
)
{
Block
*
b
=
*
bi
;
if
(
!
reachable_blocks
.
count
(
b
))
{
for
(
std
::
vector
<
std
::
unique_ptr
<
Instruction
>
>::
const_iterator
ii
=
b
->
getInstructions
().
cbegin
();
ii
!=
b
->
getInstructions
().
cend
();
ii
++
)
{
Instruction
*
i
=
ii
->
get
();
unreachable_definitions
.
insert
(
i
->
getResultId
());
}
}
}
}
decorations
.
erase
(
std
::
remove_if
(
decorations
.
begin
(),
decorations
.
end
(),
[
&
unreachable_definitions
](
std
::
unique_ptr
<
Instruction
>&
I
)
->
bool
{
Instruction
*
inst
=
I
.
get
();
Id
decoration_id
=
inst
->
getIdOperand
(
0
);
return
unreachable_definitions
.
count
(
decoration_id
)
!=
0
;
}),
decorations
.
end
());
}
void
Builder
::
dump
(
std
::
vector
<
unsigned
int
>&
out
)
const
{
// Header, before first instructions:
...
...
SPIRV/SpvBuilder.h
View file @
e0bc65b2
...
...
@@ -563,9 +563,15 @@ public:
// based on the type of the base and the chain of dereferences.
Id
accessChainGetInferredType
();
// Remove OpDecorate instructions whose operands are defined in unreachable
// blocks.
void
eliminateDeadDecorations
();
// Add capabilities, extensions, remove unneeded decorations, etc.,
// based on the resulting SPIR-V.
void
postProcess
();
// Hook to visit each instruction in a block in a function
void
postProcess
(
Instruction
&
inst
);
// Hook to visit each instruction in a reachable block in a function.
void
postProcessReachable
(
Instruction
&
inst
);
void
dump
(
std
::
vector
<
unsigned
int
>&
)
const
;
void
createBranch
(
Block
*
block
);
...
...
SPIRV/SpvPostProcess.cpp
0 → 100755
View file @
e0bc65b2
//
// Copyright (C) 2016-2018 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.
//
// Post-processing for SPIR-V IR, in internal form, not standard binary form.
//
#include <cassert>
#include <cstdlib>
#include <unordered_set>
#include <algorithm>
#include "SpvBuilder.h"
#include "spirv.hpp"
#include "GlslangToSpv.h"
#include "SpvBuilder.h"
namespace
spv
{
#include "GLSL.std.450.h"
#include "GLSL.ext.KHR.h"
#include "GLSL.ext.EXT.h"
#ifdef AMD_EXTENSIONS
#include "GLSL.ext.AMD.h"
#endif
#ifdef NV_EXTENSIONS
#include "GLSL.ext.NV.h"
#endif
}
namespace
spv
{
// Called for each instruction in a block.
void
Builder
::
postProcess
(
Instruction
&
inst
)
{
// Add capabilities based simply on the opcode.
switch
(
inst
.
getOpCode
())
{
case
OpExtInst
:
switch
(
inst
.
getIdOperand
(
1
))
{
case
GLSLstd450InterpolateAtCentroid
:
case
GLSLstd450InterpolateAtSample
:
case
GLSLstd450InterpolateAtOffset
:
addCapability
(
CapabilityInterpolationFunction
);
break
;
default
:
break
;
}
break
;
case
OpDPdxFine
:
case
OpDPdyFine
:
case
OpFwidthFine
:
case
OpDPdxCoarse
:
case
OpDPdyCoarse
:
case
OpFwidthCoarse
:
addCapability
(
CapabilityDerivativeControl
);
break
;
case
OpImageQueryLod
:
case
OpImageQuerySize
:
case
OpImageQuerySizeLod
:
case
OpImageQuerySamples
:
case
OpImageQueryLevels
:
addCapability
(
CapabilityImageQuery
);
break
;
#ifdef NV_EXTENSIONS
case
OpGroupNonUniformPartitionNV
:
addExtension
(
E_SPV_NV_shader_subgroup_partitioned
);
addCapability
(
CapabilityGroupNonUniformPartitionedNV
);
break
;
#endif
default
:
break
;
}
}
// Called for each instruction in a reachable block.
void
Builder
::
postProcessReachable
(
Instruction
&
inst
)
{
// did have code here, but questionable to do so without deleting the instructions
}
// comment in header
void
Builder
::
postProcess
()
{
std
::
unordered_set
<
const
Block
*>
reachableBlocks
;
std
::
unordered_set
<
Id
>
unreachableDefinitions
;
// Collect IDs defined in unreachable blocks. For each function, label the
// reachable blocks first. Then for each unreachable block, collect the
// result IDs of the instructions in it.
for
(
auto
fi
=
module
.
getFunctions
().
cbegin
();
fi
!=
module
.
getFunctions
().
cend
();
fi
++
)
{
Function
*
f
=
*
fi
;
Block
*
entry
=
f
->
getEntryBlock
();
inReadableOrder
(
entry
,
[
&
reachableBlocks
](
const
Block
*
b
)
{
reachableBlocks
.
insert
(
b
);
});
for
(
auto
bi
=
f
->
getBlocks
().
cbegin
();
bi
!=
f
->
getBlocks
().
cend
();
bi
++
)
{
Block
*
b
=
*
bi
;
if
(
reachableBlocks
.
count
(
b
)
==
0
)
{
for
(
auto
ii
=
b
->
getInstructions
().
cbegin
();
ii
!=
b
->
getInstructions
().
cend
();
ii
++
)
unreachableDefinitions
.
insert
(
ii
->
get
()
->
getResultId
());
}
}
}
// Remove unneeded decorations, for unreachable instructions
decorations
.
erase
(
std
::
remove_if
(
decorations
.
begin
(),
decorations
.
end
(),
[
&
unreachableDefinitions
](
std
::
unique_ptr
<
Instruction
>&
I
)
->
bool
{
Id
decoration_id
=
I
.
get
()
->
getIdOperand
(
0
);
return
unreachableDefinitions
.
count
(
decoration_id
)
!=
0
;
}),
decorations
.
end
());
// Add per-instruction capabilities, extensions, etc.,
// process all reachable instructions...
for
(
auto
bi
=
reachableBlocks
.
cbegin
();
bi
!=
reachableBlocks
.
cend
();
++
bi
)
{
const
Block
*
block
=
*
bi
;
const
auto
function
=
[
this
](
const
std
::
unique_ptr
<
Instruction
>&
inst
)
{
postProcessReachable
(
*
inst
.
get
());
};
std
::
for_each
(
block
->
getInstructions
().
begin
(),
block
->
getInstructions
().
end
(),
function
);
}
// process all block-contained instructions
for
(
auto
fi
=
module
.
getFunctions
().
cbegin
();
fi
!=
module
.
getFunctions
().
cend
();
fi
++
)
{
Function
*
f
=
*
fi
;
for
(
auto
bi
=
f
->
getBlocks
().
cbegin
();
bi
!=
f
->
getBlocks
().
cend
();
bi
++
)
{
Block
*
b
=
*
bi
;
for
(
auto
ii
=
b
->
getInstructions
().
cbegin
();
ii
!=
b
->
getInstructions
().
cend
();
ii
++
)
postProcess
(
*
ii
->
get
());
}
}
}
};
// end spv namespace
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment