Debug name part implementation (#264)
* Add documentation with source-level debugging with HLSL and DXIL. * Fix trailing underscore in generate .rst documentation. * Add container support for debug name part. * Bump validator version to 1.1. * Implement debug stripping in dxc, including /Fd dir-named behavior. * Implement IDxcCompiler2 and CompileWithDebug.
This commit is contained in:
Родитель
4bca8da154
Коммит
ad76d814a4
162
docs/DXIL.rst
162
docs/DXIL.rst
|
@ -1901,9 +1901,9 @@ Opcodes are defined on a dense range and will be provided as enum in a header fi
|
|||
.. <py::lines('OPCODES-RST')>hctdb_instrhelp.get_opcodes_rst()</py>
|
||||
.. OPCODES-RST:BEGIN
|
||||
|
||||
=== ============================== =================================================================================================================
|
||||
=== ============================= =================================================================================================================
|
||||
ID Name Description
|
||||
=== ============================== =================================================================================================================
|
||||
=== ============================= =================================================================================================================
|
||||
0 TempRegLoad_ Helper load operation
|
||||
1 TempRegStore_ Helper store operation
|
||||
2 MinPrecXRegLoad_ Helper load operation for minprecision
|
||||
|
@ -1961,89 +1961,89 @@ ID Name Description
|
|||
54 Dot2_ Two-dimensional vector dot-product
|
||||
55 Dot3_ Three-dimensional vector dot-product
|
||||
56 Dot4_ Four-dimensional vector dot-product
|
||||
57 CreateHandle_ creates the handle to a resource
|
||||
58 CBufferLoad_ loads a value from a constant buffer resource
|
||||
59 CBufferLoadLegacy_ loads a value from a constant buffer resource
|
||||
60 Sample_ samples a texture
|
||||
61 SampleBias_ samples a texture after applying the input bias to the mipmap level
|
||||
62 SampleLevel_ samples a texture using a mipmap-level offset
|
||||
63 SampleGrad_ samples a texture using a gradient to influence the way the sample location is calculated
|
||||
64 SampleCmp_ samples a texture and compares a single component against the specified comparison value
|
||||
65 SampleCmpLevelZero_ samples a texture and compares a single component against the specified comparison value
|
||||
66 TextureLoad_ reads texel data without any filtering or sampling
|
||||
67 TextureStore_ reads texel data without any filtering or sampling
|
||||
68 BufferLoad_ reads from a TypedBuffer
|
||||
69 BufferStore_ writes to a RWTypedBuffer
|
||||
70 BufferUpdateCounter_ atomically increments/decrements the hidden 32-bit counter stored with a Count or Append UAV
|
||||
71 CheckAccessFullyMapped_ determines whether all values from a Sample, Gather, or Load operation accessed mapped tiles in a tiled resource
|
||||
72 GetDimensions_ gets texture size information
|
||||
73 TextureGather_ gathers the four texels that would be used in a bi-linear filtering operation
|
||||
74 TextureGatherCmp_ same as TextureGather, except this instrution performs comparison on texels, similar to SampleCmp
|
||||
75 Texture2DMSGetSamplePosition_ gets the position of the specified sample
|
||||
76 RenderTargetGetSamplePosition_ gets the position of the specified sample
|
||||
77 RenderTargetGetSampleCount_ gets the number of samples for a render target
|
||||
78 AtomicBinOp_ performs an atomic operation on two operands
|
||||
79 AtomicCompareExchange_ atomic compare and exchange to memory
|
||||
80 Barrier_ inserts a memory barrier in the shader
|
||||
81 CalculateLOD_ calculates the level of detail
|
||||
82 Discard_ discard the current pixel
|
||||
57 CreateHandle creates the handle to a resource
|
||||
58 CBufferLoad loads a value from a constant buffer resource
|
||||
59 CBufferLoadLegacy loads a value from a constant buffer resource
|
||||
60 Sample samples a texture
|
||||
61 SampleBias samples a texture after applying the input bias to the mipmap level
|
||||
62 SampleLevel samples a texture using a mipmap-level offset
|
||||
63 SampleGrad samples a texture using a gradient to influence the way the sample location is calculated
|
||||
64 SampleCmp samples a texture and compares a single component against the specified comparison value
|
||||
65 SampleCmpLevelZero samples a texture and compares a single component against the specified comparison value
|
||||
66 TextureLoad reads texel data without any filtering or sampling
|
||||
67 TextureStore reads texel data without any filtering or sampling
|
||||
68 BufferLoad reads from a TypedBuffer
|
||||
69 BufferStore writes to a RWTypedBuffer
|
||||
70 BufferUpdateCounter atomically increments/decrements the hidden 32-bit counter stored with a Count or Append UAV
|
||||
71 CheckAccessFullyMapped determines whether all values from a Sample, Gather, or Load operation accessed mapped tiles in a tiled resource
|
||||
72 GetDimensions gets texture size information
|
||||
73 TextureGather gathers the four texels that would be used in a bi-linear filtering operation
|
||||
74 TextureGatherCmp same as TextureGather, except this instrution performs comparison on texels, similar to SampleCmp
|
||||
75 Texture2DMSGetSamplePosition gets the position of the specified sample
|
||||
76 RenderTargetGetSamplePosition gets the position of the specified sample
|
||||
77 RenderTargetGetSampleCount gets the number of samples for a render target
|
||||
78 AtomicBinOp performs an atomic operation on two operands
|
||||
79 AtomicCompareExchange atomic compare and exchange to memory
|
||||
80 Barrier inserts a memory barrier in the shader
|
||||
81 CalculateLOD calculates the level of detail
|
||||
82 Discard discard the current pixel
|
||||
83 DerivCoarseX_ computes the rate of change per stamp in x direction.
|
||||
84 DerivCoarseY_ computes the rate of change per stamp in y direction.
|
||||
85 DerivFineX_ computes the rate of change per pixel in x direction.
|
||||
86 DerivFineY_ computes the rate of change per pixel in y direction.
|
||||
87 EvalSnapped_ evaluates an input attribute at pixel center with an offset
|
||||
88 EvalSampleIndex_ evaluates an input attribute at a sample location
|
||||
89 EvalCentroid_ evaluates an input attribute at pixel center
|
||||
90 SampleIndex_ returns the sample index in a sample-frequency pixel shader
|
||||
91 Coverage_ returns the coverage mask input in a pixel shader
|
||||
92 InnerCoverage_ returns underestimated coverage input from conservative rasterization in a pixel shader
|
||||
93 ThreadId_ reads the thread ID
|
||||
94 GroupId_ reads the group ID (SV_GroupID)
|
||||
95 ThreadIdInGroup_ reads the thread ID within the group (SV_GroupThreadID)
|
||||
96 FlattenedThreadIdInGroup_ provides a flattened index for a given thread within a given group (SV_GroupIndex)
|
||||
97 EmitStream_ emits a vertex to a given stream
|
||||
98 CutStream_ completes the current primitive topology at the specified stream
|
||||
99 EmitThenCutStream_ equivalent to an EmitStream followed by a CutStream
|
||||
100 GSInstanceID_ GSInstanceID
|
||||
101 MakeDouble_ creates a double value
|
||||
102 SplitDouble_ splits a double into low and high parts
|
||||
103 LoadOutputControlPoint_ LoadOutputControlPoint
|
||||
104 LoadPatchConstant_ LoadPatchConstant
|
||||
105 DomainLocation_ DomainLocation
|
||||
106 StorePatchConstant_ StorePatchConstant
|
||||
107 OutputControlPointID_ OutputControlPointID
|
||||
108 PrimitiveID_ PrimitiveID
|
||||
109 CycleCounterLegacy_ CycleCounterLegacy
|
||||
110 WaveIsFirstLane_ returns 1 for the first lane in the wave
|
||||
111 WaveGetLaneIndex_ returns the index of the current lane in the wave
|
||||
112 WaveGetLaneCount_ returns the number of lanes in the wave
|
||||
113 WaveAnyTrue_ returns 1 if any of the lane evaluates the value to true
|
||||
114 WaveAllTrue_ returns 1 if all the lanes evaluate the value to true
|
||||
115 WaveActiveAllEqual_ returns 1 if all the lanes have the same value
|
||||
116 WaveActiveBallot_ returns a struct with a bit set for each lane where the condition is true
|
||||
117 WaveReadLaneAt_ returns the value from the specified lane
|
||||
118 WaveReadLaneFirst_ returns the value from the first lane
|
||||
119 WaveActiveOp_ returns the result the operation across waves
|
||||
120 WaveActiveBit_ returns the result of the operation across all lanes
|
||||
121 WavePrefixOp_ returns the result of the operation on prior lanes
|
||||
122 QuadReadLaneAt_ reads from a lane in the quad
|
||||
123 QuadOp_ returns the result of a quad-level operation
|
||||
124 BitcastI16toF16_ bitcast between different sizes
|
||||
125 BitcastF16toI16_ bitcast between different sizes
|
||||
126 BitcastI32toF32_ bitcast between different sizes
|
||||
127 BitcastF32toI32_ bitcast between different sizes
|
||||
128 BitcastI64toF64_ bitcast between different sizes
|
||||
129 BitcastF64toI64_ bitcast between different sizes
|
||||
130 LegacyF32ToF16_ legacy fuction to convert float (f32) to half (f16) (this is not related to min-precision)
|
||||
131 LegacyF16ToF32_ legacy fuction to convert half (f16) to float (f32) (this is not related to min-precision)
|
||||
132 LegacyDoubleToFloat_ legacy fuction to convert double to float
|
||||
133 LegacyDoubleToSInt32_ legacy fuction to convert double to int32
|
||||
134 LegacyDoubleToUInt32_ legacy fuction to convert double to uint32
|
||||
135 WaveAllBitCount_ returns the count of bits set to 1 across the wave
|
||||
136 WavePrefixBitCount_ returns the count of bits set to 1 on prior lanes
|
||||
87 EvalSnapped evaluates an input attribute at pixel center with an offset
|
||||
88 EvalSampleIndex evaluates an input attribute at a sample location
|
||||
89 EvalCentroid evaluates an input attribute at pixel center
|
||||
90 SampleIndex returns the sample index in a sample-frequency pixel shader
|
||||
91 Coverage returns the coverage mask input in a pixel shader
|
||||
92 InnerCoverage returns underestimated coverage input from conservative rasterization in a pixel shader
|
||||
93 ThreadId reads the thread ID
|
||||
94 GroupId reads the group ID (SV_GroupID)
|
||||
95 ThreadIdInGroup reads the thread ID within the group (SV_GroupThreadID)
|
||||
96 FlattenedThreadIdInGroup provides a flattened index for a given thread within a given group (SV_GroupIndex)
|
||||
97 EmitStream emits a vertex to a given stream
|
||||
98 CutStream completes the current primitive topology at the specified stream
|
||||
99 EmitThenCutStream equivalent to an EmitStream followed by a CutStream
|
||||
100 GSInstanceID GSInstanceID
|
||||
101 MakeDouble creates a double value
|
||||
102 SplitDouble splits a double into low and high parts
|
||||
103 LoadOutputControlPoint LoadOutputControlPoint
|
||||
104 LoadPatchConstant LoadPatchConstant
|
||||
105 DomainLocation DomainLocation
|
||||
106 StorePatchConstant StorePatchConstant
|
||||
107 OutputControlPointID OutputControlPointID
|
||||
108 PrimitiveID PrimitiveID
|
||||
109 CycleCounterLegacy CycleCounterLegacy
|
||||
110 WaveIsFirstLane returns 1 for the first lane in the wave
|
||||
111 WaveGetLaneIndex returns the index of the current lane in the wave
|
||||
112 WaveGetLaneCount returns the number of lanes in the wave
|
||||
113 WaveAnyTrue returns 1 if any of the lane evaluates the value to true
|
||||
114 WaveAllTrue returns 1 if all the lanes evaluate the value to true
|
||||
115 WaveActiveAllEqual returns 1 if all the lanes have the same value
|
||||
116 WaveActiveBallot returns a struct with a bit set for each lane where the condition is true
|
||||
117 WaveReadLaneAt returns the value from the specified lane
|
||||
118 WaveReadLaneFirst returns the value from the first lane
|
||||
119 WaveActiveOp returns the result the operation across waves
|
||||
120 WaveActiveBit returns the result of the operation across all lanes
|
||||
121 WavePrefixOp returns the result of the operation on prior lanes
|
||||
122 QuadReadLaneAt reads from a lane in the quad
|
||||
123 QuadOp returns the result of a quad-level operation
|
||||
124 BitcastI16toF16 bitcast between different sizes
|
||||
125 BitcastF16toI16 bitcast between different sizes
|
||||
126 BitcastI32toF32 bitcast between different sizes
|
||||
127 BitcastF32toI32 bitcast between different sizes
|
||||
128 BitcastI64toF64 bitcast between different sizes
|
||||
129 BitcastF64toI64 bitcast between different sizes
|
||||
130 LegacyF32ToF16 legacy fuction to convert float (f32) to half (f16) (this is not related to min-precision)
|
||||
131 LegacyF16ToF32 legacy fuction to convert half (f16) to float (f32) (this is not related to min-precision)
|
||||
132 LegacyDoubleToFloat legacy fuction to convert double to float
|
||||
133 LegacyDoubleToSInt32 legacy fuction to convert double to int32
|
||||
134 LegacyDoubleToUInt32 legacy fuction to convert double to uint32
|
||||
135 WaveAllBitCount returns the count of bits set to 1 across the wave
|
||||
136 WavePrefixBitCount returns the count of bits set to 1 on prior lanes
|
||||
137 AttributeAtVertex_ returns the values of the attributes at the vertex.
|
||||
138 ViewID_ returns the view index
|
||||
=== ============================== =================================================================================================================
|
||||
138 ViewID returns the view index
|
||||
=== ============================= =================================================================================================================
|
||||
|
||||
|
||||
Acos
|
||||
|
@ -2902,6 +2902,8 @@ Support is provided in the Microsoft Windows family of operating systems, when r
|
|||
|
||||
The HLSL language is versioned independently of DXIL, and currently follows an 'HLSL <year>' naming scheme. HLSL 2015 is the dialect supported by the d3dcompiler_47 library; a limited form of support is provided in the open source HLSL on LLVM project. HLSL 2016 is the version supported by the current HLSL on LLVM project, which removes some features (primarily effect framework syntax, backquote operator) and adds new ones (wave intrinsics and basic i64 support).
|
||||
|
||||
.. _dxil_container_format:
|
||||
|
||||
DXIL Container Format
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@ information takes <format>`, which is useful for those interested in creating
|
|||
front-ends or dealing directly with the information. Further, this document
|
||||
provides specific examples of what debug information for C/C++ looks like.
|
||||
|
||||
HLSL and DXIL-specific information is available in the :doc:`Source Level
|
||||
Debugging with HLSL <SourceLevelDebuggingHLSL>` document.
|
||||
|
||||
Philosophy behind LLVM debugging information
|
||||
--------------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
================================
|
||||
Source Level Debugging with HLSL
|
||||
================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document describes the specifics of source level debuging with HLSL. The
|
||||
basic infrastructure is based on :doc:`Source Level Debugging with LLVM
|
||||
<SourceLevelDebugging>`, so the focus here is on the specifics of DXIL
|
||||
programs compiled from HLSL.
|
||||
|
||||
DXIL Debug Information Format
|
||||
=============================
|
||||
|
||||
The debug information for an HLSL program in DXIL form is stored as an LLVM
|
||||
module with debug information represented according to the :doc:`Source Level
|
||||
Debugging with LLVM <SourceLevelDebugging>` document.
|
||||
|
||||
The :ref:`dxil_container_format` describes how a single data structure
|
||||
holds both a DXIL program, debug information, and other optional parts.
|
||||
|
||||
There are three parts that are associated with debug information.
|
||||
|
||||
* DFCC_DXIL ('DXIL'). A valid DXIL program has no debug information. This is
|
||||
the program described by debug information.
|
||||
|
||||
* DFCC_ShaderDebugInfoDXIL ('ILDB'). This is an LLVM module with debug
|
||||
information. It's an augmented version of the original DXIL module. For
|
||||
historical reasons, this is sometimes referred to as 'the PDB of the
|
||||
program'.
|
||||
|
||||
* DFCC_ShaderDebugName ('ILDN'). This is a name for an external entity holding
|
||||
the debug information.
|
||||
|
||||
Using Debug Information
|
||||
=======================
|
||||
|
||||
The debug information can be used directly by looking up the debug information
|
||||
part and loading into an LLVM module. There is full fidelity with debug
|
||||
information via this mechanism, although it requires linking in the LLVM
|
||||
supporting libraries.
|
||||
|
||||
For compatibility, the dxcompiler.dll binary also exposes a limited
|
||||
implementation of the DIA APIs. To do this, a CLSID_DxcDiaDataSource class
|
||||
should be created via a call to DxcCreateInstance, and a loadDataFromIStream
|
||||
call with the debug part will initialize it.
|
||||
|
||||
The DxcContext::Recompile implementation provides an example of how to
|
||||
initialize the diagnostic objects from debug information, extract high-level
|
||||
information and recreate the compilation options and inputs.
|
||||
|
||||
Using Debug Names
|
||||
=================
|
||||
|
||||
The only current use case for the debug name is as a relative path to a file
|
||||
that provides shader debug information. A debugging tool would typically have
|
||||
a list of paths to act as search roots.
|
||||
|
||||
Command-Line Options
|
||||
====================
|
||||
|
||||
The following command-line options are used with the DirectX Shader Compiler
|
||||
tools to work with debug information.
|
||||
|
||||
* /Zi. Enables debug information during compilation.
|
||||
|
||||
* /Zss. Builds debug names that consider source information.
|
||||
|
||||
* /Zsb. Builds debug names that consider only the output binary.
|
||||
|
||||
* /Fd. Extracts debug information to a different file.
|
||||
|
||||
* /Qstrip_debug. Removes debug information from a container.
|
||||
|
||||
The most common use cases are as follows.
|
||||
|
||||
* Build debug information and leave it in the container. In this case, simply
|
||||
compiling with /Zi will do the trick.
|
||||
|
||||
* Build debug information and extract it to an auto-generated external
|
||||
file. In this case, /Zi and /Fd should both be used, and the /Fd value
|
||||
should end in a trailing backslash when using dxc, naming the target
|
||||
directory in which to place the file. /Zss is the default, but /Zsb can be
|
||||
used to deduplicate files. When using /Fd with a directory name,
|
||||
/Qstrip_debug is implied.
|
||||
|
||||
A less common use case is to specify an explicit name for the external
|
||||
file. In this case, the command-line should include /Zi, /Fd with a specific
|
||||
name, and /Qstrip_debug.
|
||||
|
||||
Implementation Notes
|
||||
====================
|
||||
|
||||
The current implementation provides a few interesting behaviors worth noting.
|
||||
|
||||
* The shader debug name is derived from either the DXIL or the ILDB parts by
|
||||
hashing the byte contents, but it can be replaced programmatically.
|
||||
|
||||
* Source content is included in the debug information blob by default. This
|
||||
helps with scenarios where the code never exists on-disk, but is instead
|
||||
generated on-the-fly.
|
||||
|
||||
* Typically the derivation is done from the ILDB part, which includes
|
||||
source-specific information, and so two shaders with different sources will
|
||||
have different debug information. However the option is provided via (-Zsb)
|
||||
to include debug information that only takes into consideration the DXIL
|
||||
binary. In this case, two shaders that compile to the same binary will have
|
||||
the same debug information, which can be used to deduplicate content when
|
||||
any equivalent source program is acceptable for debugging.
|
||||
|
||||
Future Directions
|
||||
=================
|
||||
|
||||
This section is purely speculative, but captures some of the thoughts about
|
||||
future debugging capabilities.
|
||||
|
||||
* If driver-level constructs should be debugged, they need to be mapped to
|
||||
DXIL first, and from there on to HLSL.
|
||||
|
||||
* Including content in debug is convenient, especially when sources are
|
||||
transient, but they are inefficient (again, especially for a large number of
|
||||
transient sources). Deduplicating sources would be beneficial.
|
||||
|
||||
* Integration with symbol servers and source servers can simplify some of the
|
||||
developer workflows.
|
||||
|
|
@ -170,6 +170,7 @@ For API clients and LLVM developers.
|
|||
MarkedUpDisassembly
|
||||
SystemLibrary
|
||||
SourceLevelDebugging
|
||||
SourceLevelDebuggingHLSL
|
||||
Vectorizers
|
||||
WritingAnLLVMBackend
|
||||
WritingAnLLVMPass
|
||||
|
@ -204,6 +205,10 @@ For API clients and LLVM developers.
|
|||
This document describes the design and philosophy behind the LLVM
|
||||
source-level debugger.
|
||||
|
||||
:doc:`Source Level Debugging with HLSL <SourceLevelDebuggingHLSL>`
|
||||
This document describes specifics of using source-level debuggers for DXIL
|
||||
and HLSL.
|
||||
|
||||
:doc:`Vectorizers`
|
||||
This document describes the current status of vectorization in LLVM.
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ enum DxilFourCC {
|
|||
DFCC_PatchConstantSignature = DXIL_FOURCC('P', 'S', 'G', '1'),
|
||||
DFCC_ShaderStatistics = DXIL_FOURCC('S', 'T', 'A', 'T'),
|
||||
DFCC_ShaderDebugInfoDXIL = DXIL_FOURCC('I', 'L', 'D', 'B'),
|
||||
DFCC_ShaderDebugName = DXIL_FOURCC('I', 'L', 'D', 'N'),
|
||||
DFCC_FeatureInfo = DXIL_FOURCC('S', 'F', 'I', '0'),
|
||||
DFCC_PrivateData = DXIL_FOURCC('P', 'R', 'I', 'V'),
|
||||
DFCC_RootSignature = DXIL_FOURCC('R', 'T', 'S', '0'),
|
||||
|
@ -105,8 +106,7 @@ static const uint64_t ShaderFeatureInfo_Int64Ops = 0x8000;
|
|||
|
||||
static const unsigned ShaderFeatureInfoCount = 16;
|
||||
|
||||
struct DxilShaderFeatureInfo
|
||||
{
|
||||
struct DxilShaderFeatureInfo {
|
||||
uint64_t FeatureFlags;
|
||||
};
|
||||
|
||||
|
@ -210,6 +210,15 @@ struct DxilProgramSignatureElement {
|
|||
// Easy to get this wrong. Earlier assertions can help determine
|
||||
static_assert(sizeof(DxilProgramSignatureElement) == 0x20, "else DxilProgramSignatureElement is misaligned");
|
||||
|
||||
struct DxilShaderDebugName {
|
||||
uint16_t Flags; // Reserved, must be set to zero.
|
||||
uint16_t NameLength; // Length of the debug name, without null terminator.
|
||||
// Followed by NameLength bytes of the UTF-8-encoded name.
|
||||
// Followed by a null terminator.
|
||||
// Followed by [0-3] zero bytes to align to a 4-byte boundary.
|
||||
};
|
||||
static const size_t MinDxilShaderDebugNameSize = sizeof(DxilShaderDebugName) + 4;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/// Gets a part header by index.
|
||||
|
@ -376,6 +385,33 @@ inline uint32_t EncodeVersion(DXIL::ShaderKind shaderType, uint32_t major,
|
|||
return ((unsigned)shaderType << 16) | (major << 4) | minor;
|
||||
}
|
||||
|
||||
inline bool IsDxilShaderDebugNameValid(const DxilPartHeader *pPart) {
|
||||
if (pPart->PartFourCC != DFCC_ShaderDebugName) return false;
|
||||
if (pPart->PartSize < MinDxilShaderDebugNameSize) return false;
|
||||
const DxilShaderDebugName *pDebugNameContent = reinterpret_cast<const DxilShaderDebugName *>(GetDxilPartData(pPart));
|
||||
uint16_t ExpectedSize = sizeof(DxilShaderDebugName) + pDebugNameContent->NameLength + 1;
|
||||
if (ExpectedSize & 0x3) {
|
||||
ExpectedSize += 0x4;
|
||||
ExpectedSize &= ~(0x3);
|
||||
}
|
||||
if (pPart->PartSize != ExpectedSize) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetDxilShaderDebugName(const DxilPartHeader *pDebugNamePart,
|
||||
const char **ppUtf8Name, _Out_opt_ uint16_t *pUtf8NameLen) {
|
||||
*ppUtf8Name = nullptr;
|
||||
if (!IsDxilShaderDebugNameValid(pDebugNamePart)) {
|
||||
return false;
|
||||
}
|
||||
const DxilShaderDebugName *pDebugNameContent = reinterpret_cast<const DxilShaderDebugName *>(GetDxilPartData(pDebugNamePart));
|
||||
if (pUtf8NameLen) {
|
||||
*pUtf8NameLen = pDebugNameContent->NameLength;
|
||||
}
|
||||
*ppUtf8Name = (const char *)(pDebugNameContent + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
class DxilPartWriter {
|
||||
public:
|
||||
virtual ~DxilPartWriter() {}
|
||||
|
@ -397,9 +433,24 @@ public:
|
|||
|
||||
DxilContainerWriter *NewDxilContainerWriter();
|
||||
|
||||
enum class SerializeDxilFlags {
|
||||
None = 0, // No flags defined.
|
||||
IncludeDebugInfoPart = 1, // Include the debug info part in the container.
|
||||
IncludeDebugNamePart = 2, // Include the debug name part in the container.
|
||||
DebugNameDependOnSource = 4 // Make the debug name depend on source (and not just final module).
|
||||
};
|
||||
inline SerializeDxilFlags& operator |=(SerializeDxilFlags& l, const SerializeDxilFlags& r) {
|
||||
l = static_cast<SerializeDxilFlags>(static_cast<int>(l) | static_cast<int>(r));
|
||||
return l;
|
||||
}
|
||||
inline int operator&(SerializeDxilFlags l, SerializeDxilFlags r) {
|
||||
return static_cast<int>(l) & static_cast<int>(r);
|
||||
}
|
||||
|
||||
void SerializeDxilContainerForModule(hlsl::DxilModule *pModule,
|
||||
AbstractMemoryStream *pModuleBitcode,
|
||||
AbstractMemoryStream *pStream);
|
||||
AbstractMemoryStream *pStream,
|
||||
SerializeDxilFlags Flags);
|
||||
void SerializeDxilContainerForRootSignature(hlsl::RootSignatureHandle *pRootSigHandle,
|
||||
AbstractMemoryStream *pStream);
|
||||
|
||||
|
|
|
@ -113,6 +113,8 @@ public:
|
|||
bool ColorCodeAssembly; // OPT_Cc
|
||||
bool CodeGenHighLevel; // OPT_fcgl
|
||||
bool DebugInfo; // OPT__SLASH_Zi
|
||||
bool DebugNameForBinary; // OPT_Zsb
|
||||
bool DebugNameForSource; // OPT_Zss
|
||||
bool DumpBin; // OPT_dumpbin
|
||||
bool WarningAsError; // OPT__SLASH_WX
|
||||
bool IEEEStrict; // OPT_Gis
|
||||
|
|
|
@ -254,6 +254,10 @@ def Zpr : Flag<["-", "/"], "Zpr">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
|
|||
HelpText<"Pack matrices in row-major order">;
|
||||
def Zpc : Flag<["-", "/"], "Zpc">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
|
||||
HelpText<"Pack matrices in column-major order">;
|
||||
def Zss : Flag<["-", "/"], "Zss">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
|
||||
HelpText<"Build debug name considering source information">;
|
||||
def Zsb : Flag<["-", "/"], "Zsb">, Flags<[CoreOption]>, Group<hlslcomp_Group>,
|
||||
HelpText<"Build debug name considering only output binary">;
|
||||
|
||||
// deprecated /Gpp def Gpp : Flag<["-", "/"], "Gpp">, HelpText<"Force partial precision">;
|
||||
def Gfa : Flag<["-", "/"], "Gfa">, HelpText<"Avoid flow control constructs">, Flags<[CoreOption]>, Group<hlslcomp_Group>;
|
||||
|
@ -267,8 +271,8 @@ def Fo : JoinedOrSeparate<["-", "/"], "Fo">, MetaVarName<"<file>">, HelpText<"Ou
|
|||
def Fc : JoinedOrSeparate<["-", "/"], "Fc">, MetaVarName<"<file>">, HelpText<"Output assembly code listing file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
|
||||
//def Fx : JoinedOrSeparate<["-", "/"], "Fx">, MetaVarName<"<file>">, HelpText<"Output assembly code and hex listing file">;
|
||||
def Fh : JoinedOrSeparate<["-", "/"], "Fh">, MetaVarName<"<file>">, HelpText<"Output header file containing object code">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
|
||||
def Fe : JoinedOrSeparate<["-", "/"], "Fe">, MetaVarName<"<file>">, HelpText<"Output warnings and errors to a specific file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
|
||||
def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"<file>">, HelpText<"Extract LLVM Debug IR and write to given file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
|
||||
def Fe : JoinedOrSeparate<["-", "/"], "Fe">, MetaVarName<"<file>">, HelpText<"Output warnings and errors to the given file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
|
||||
def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"<file>">, HelpText<"Write debug information to the given file or directory; trail \\ to auto-generate and imply Qstrip_priv">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
|
||||
def Vn : JoinedOrSeparate<["-", "/"], "Vn">, MetaVarName<"<name>">, HelpText<"Use <name> as variable name in header file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
|
||||
def Cc : Flag<["-", "/"], "Cc">, HelpText<"Output color coded assembly listings">, Group<hlslcomp_Group>, Flags<[DriverOption]>;
|
||||
def Ni : Flag<["-", "/"], "Ni">, HelpText<"Output instruction numbers in assembly listings">, Group<hlslcomp_Group>, Flags<[DriverOption]>;
|
||||
|
@ -285,7 +289,7 @@ def dumpbin : Flag<["-", "/"], "dumpbin">, Flags<[DriverOption]>, Group<hlslutil
|
|||
HelpText<"Load a binary file rather than compiling">;
|
||||
def Qstrip_reflect : Flag<["-", "/"], "Qstrip_reflect">, Flags<[DriverOption]>, Group<hlslutil_Group>,
|
||||
HelpText<"Strip reflection data from shader bytecode (must be used with /Fo <file>)">;
|
||||
def Qstrip_debug : Flag<["-", "/"], "Qstrip_debug">, Flags<[DriverOption]>, Group<hlslutil_Group>,
|
||||
def Qstrip_debug : Flag<["-", "/"], "Qstrip_debug">, Flags<[CoreOption]>, Group<hlslutil_Group>,
|
||||
HelpText<"Strip debug information from 4_0+ shader bytecode (must be used with /Fo <file>)">;
|
||||
def Qstrip_priv : Flag<["-", "/"], "Qstrip_priv">, Flags<[DriverOption]>, Group<hlslutil_Group>,
|
||||
HelpText<"Strip private data from shader bytecode (must be used with /Fo <file>)">;
|
||||
|
|
|
@ -50,6 +50,10 @@ bool IsStarMatchUTF8(_In_reads_opt_(maskLen) const char *pMask, size_t maskLen,
|
|||
bool IsStarMatchUTF16(_In_reads_opt_(maskLen) const wchar_t *pMask, size_t maskLen,
|
||||
_In_reads_opt_(nameLen) const wchar_t *pName, size_t nameLen);
|
||||
|
||||
_Success_(return != false)
|
||||
bool UTF8BufferToUTF16ComHeap(_In_z_ const char *pUTF8,
|
||||
_Outptr_result_z_ wchar_t **ppUTF16) throw();
|
||||
|
||||
_Success_(return != false)
|
||||
bool UTF8BufferToUTF16Buffer(
|
||||
_In_NLS_string_(cbUTF8) const char *pUTF8,
|
||||
|
|
|
@ -198,6 +198,28 @@ HRESULT DoBasicQueryInterface4(TObject* self, REFIID iid, void** ppvObject)
|
|||
return DoBasicQueryInterface3<TInterface, TInterface2, TInterface3, TObject>(self, iid, ppvObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a QueryInterface implementation for a class that supports
|
||||
/// five interfaces in addition to IUnknown.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation will also report the instance as not supporting
|
||||
/// marshaling. This will help catch marshaling problems early or avoid
|
||||
/// them altogether.
|
||||
/// </remarks>
|
||||
template <typename TInterface, typename TInterface2, typename TInterface3, typename TInterface4, typename TInterface5, typename TObject>
|
||||
HRESULT DoBasicQueryInterface5(TObject* self, REFIID iid, void** ppvObject)
|
||||
{
|
||||
if (ppvObject == nullptr) return E_POINTER;
|
||||
if (IsEqualIID(iid, __uuidof(TInterface5))) {
|
||||
*(TInterface5**)ppvObject = self;
|
||||
self->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return DoBasicQueryInterface4<TInterface, TInterface2, TInterface3, TInterface4, TObject>(self, iid, ppvObject);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HRESULT AssignToOut(T value, _Out_ T* pResult) {
|
||||
if (pResult == nullptr)
|
||||
|
|
|
@ -156,12 +156,32 @@ IDxcCompiler : public IUnknown {
|
|||
_COM_Outptr_ IDxcOperationResult **ppResult // Preprocessor output status, buffer, and errors
|
||||
) = 0;
|
||||
|
||||
// Disassemble a program.
|
||||
virtual HRESULT STDMETHODCALLTYPE Disassemble(
|
||||
_In_ IDxcBlob *pSource, // Program to disassemble.
|
||||
_COM_Outptr_ IDxcBlobEncoding **ppDisassembly // Disassembly text.
|
||||
) = 0;
|
||||
};
|
||||
|
||||
struct __declspec(uuid("A005A9D9-B8BB-4594-B5C9-0E633BEC4D37"))
|
||||
IDxcCompiler2 : public IDxcCompiler {
|
||||
// Compile a single entry point to the target shader model with debug information.
|
||||
virtual HRESULT STDMETHODCALLTYPE CompileWithDebug(
|
||||
_In_ IDxcBlob *pSource, // Source text to compile
|
||||
_In_opt_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers.
|
||||
_In_ LPCWSTR pEntryPoint, // Entry point name
|
||||
_In_ LPCWSTR pTargetProfile, // Shader profile to compile
|
||||
_In_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments
|
||||
_In_ UINT32 argCount, // Number of arguments
|
||||
_In_count_(defineCount) const DxcDefine *pDefines, // Array of defines
|
||||
_In_ UINT32 defineCount, // Number of defines
|
||||
_In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional)
|
||||
_COM_Outptr_ IDxcOperationResult **ppResult, // Compiler output status, buffer, and errors
|
||||
_Outptr_opt_result_z_ LPWSTR *ppDebugBlobName,// Suggested file name for debug blob.
|
||||
_COM_Outptr_opt_ IDxcBlob **ppDebugBlob // Debug blob
|
||||
) = 0;
|
||||
};
|
||||
|
||||
static const UINT32 DxcValidatorFlags_Default = 0;
|
||||
static const UINT32 DxcValidatorFlags_InPlaceEdit = 1; // Validator is allowed to update shader blob in-place.
|
||||
static const UINT32 DxcValidatorFlags_RootSignatureOnly = 2;
|
||||
|
|
|
@ -252,6 +252,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
|
|||
opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false); // SPIRV change
|
||||
opts.CodeGenHighLevel = Args.hasFlag(OPT_fcgl, OPT_INVALID, false);
|
||||
opts.DebugInfo = Args.hasFlag(OPT__SLASH_Zi, OPT_INVALID, false);
|
||||
opts.DebugNameForBinary = Args.hasFlag(OPT_Zsb, OPT_INVALID, false);
|
||||
opts.DebugNameForSource = Args.hasFlag(OPT_Zsb, OPT_INVALID, false);
|
||||
opts.VariableName = Args.getLastArgValue(OPT_Vn);
|
||||
opts.InputFile = Args.getLastArgValue(OPT_INPUT);
|
||||
opts.ForceRootSigVer = Args.getLastArgValue(OPT_force_rootsig_ver);
|
||||
|
@ -375,6 +377,14 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!opts.DebugNameForBinary && !opts.DebugNameForSource) {
|
||||
opts.DebugNameForSource = true;
|
||||
}
|
||||
else if (opts.DebugNameForBinary && opts.DebugNameForSource) {
|
||||
errors << "Cannot specify both /Zss and /Zsb";
|
||||
return 1;
|
||||
}
|
||||
|
||||
opts.Args = std::move(Args);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -122,6 +122,22 @@ std::string UTF16ToUTF8StringOrThrow(_In_z_ const wchar_t *pUTF16) {
|
|||
return result;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
bool UTF8BufferToUTF16ComHeap(const char *pUTF8, wchar_t **ppUTF16) throw() {
|
||||
*ppUTF16 = nullptr;
|
||||
int c = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, pUTF8, -1,
|
||||
nullptr, 0);
|
||||
if (c == 0)
|
||||
return false;
|
||||
CComHeapPtr<wchar_t> p;
|
||||
if (!p.Allocate(c))
|
||||
return false;
|
||||
DXVERIFY_NOMSG(0 < ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, pUTF8,
|
||||
-1, p.m_pData, c));
|
||||
*ppUTF16 = p.Detach();
|
||||
return true;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
bool UTF8BufferToUTF16Buffer(const char *pUTF8, int cbUTF8, wchar_t **ppUTF16, size_t *pcUTF16) throw() {
|
||||
*ppUTF16 = nullptr;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/Bitcode/ReaderWriter.h"
|
||||
#include "llvm/Support/MD5.h"
|
||||
#include "dxc/HLSL/DxilContainer.h"
|
||||
#include "dxc/HLSL/DxilModule.h"
|
||||
#include "dxc/HLSL/DxilShaderModel.h"
|
||||
|
@ -612,7 +613,8 @@ static void WriteProgramPart(const ShaderModel *pModel,
|
|||
|
||||
void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
|
||||
AbstractMemoryStream *pModuleBitcode,
|
||||
AbstractMemoryStream *pFinalStream) {
|
||||
AbstractMemoryStream *pFinalStream,
|
||||
SerializeDxilFlags Flags) {
|
||||
// TODO: add a flag to update the module and remove information that is not part
|
||||
// of DXIL proper and is used only to assemble the container.
|
||||
|
||||
|
@ -680,9 +682,11 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
|
|||
if (HasDebugInfo(*pModule->GetModule())) {
|
||||
uint32_t debugInUInt32, debugPaddingBytes;
|
||||
GetPaddedProgramPartSize(pInputProgramStream, debugInUInt32, debugPaddingBytes);
|
||||
if (Flags & SerializeDxilFlags::IncludeDebugInfoPart) {
|
||||
writer.AddPart(DFCC_ShaderDebugInfoDXIL, debugInUInt32 * sizeof(uint32_t) + sizeof(DxilProgramHeader), [&](AbstractMemoryStream *pStream) {
|
||||
WriteProgramPart(pModule->GetShaderModel(), pInputProgramStream, pStream);
|
||||
});
|
||||
}
|
||||
|
||||
pProgramStream.Release();
|
||||
|
||||
|
@ -694,6 +698,39 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
|
|||
IFT(CreateMemoryStream(pMalloc, &pProgramStream));
|
||||
raw_stream_ostream outStream(pProgramStream.p);
|
||||
WriteBitcodeToFile(pModule->GetModule(), outStream, true);
|
||||
|
||||
if (Flags & SerializeDxilFlags::IncludeDebugNamePart) {
|
||||
CComPtr<AbstractMemoryStream> pHashStream;
|
||||
// If the debug name should be specific to the sources, base the name on the debug
|
||||
// bitcode, which will include the source references, line numbers, etc. Otherwise,
|
||||
// do it exclusively on the target shader bitcode.
|
||||
pHashStream = (int)(Flags & SerializeDxilFlags::DebugNameDependOnSource) ? pModuleBitcode : pProgramStream;
|
||||
const uint32_t DebugInfoNameHashLen = 32; // 32 chars of MD5
|
||||
const uint32_t DebugInfoNameSuffix = 4; // '.lld'
|
||||
const uint32_t DebugInfoNameNullAndPad = 4; // '\0\0\0\0'
|
||||
const uint32_t DebugInfoContentLen =
|
||||
sizeof(DxilShaderDebugName) + DebugInfoNameHashLen +
|
||||
DebugInfoNameSuffix + DebugInfoNameNullAndPad;
|
||||
writer.AddPart(DFCC_ShaderDebugName, DebugInfoContentLen, [&](AbstractMemoryStream *pStream) {
|
||||
DxilShaderDebugName NameContent;
|
||||
NameContent.Flags = 0;
|
||||
NameContent.NameLength = DebugInfoNameHashLen + DebugInfoNameSuffix;
|
||||
IFT(WriteStreamValue(pStream, NameContent));
|
||||
|
||||
ArrayRef<uint8_t> Data((uint8_t *)pHashStream->GetPtr(), pHashStream->GetPtrSize());
|
||||
llvm::MD5 md5;
|
||||
llvm::MD5::MD5Result md5Result;
|
||||
SmallString<32> Hash;
|
||||
md5.update(Data);
|
||||
md5.final(md5Result);
|
||||
md5.stringifyResult(md5Result, Hash);
|
||||
|
||||
ULONG cbWritten;
|
||||
IFT(pStream->Write(Hash.data(), Hash.size(), &cbWritten));
|
||||
const char SuffixAndPad[] = ".lld\0\0\0";
|
||||
IFT(pStream->Write(SuffixAndPad, _countof(SuffixAndPad), &cbWritten));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Compute padded bitcode size.
|
||||
|
|
|
@ -4070,7 +4070,9 @@ static void ValidateUninitializedOutput(ValidationContext &ValCtx) {
|
|||
}
|
||||
|
||||
void GetValidationVersion(_Out_ unsigned *pMajor, _Out_ unsigned *pMinor) {
|
||||
// Bump these versions after 1.0 to account for additional validation rules.
|
||||
// 1.0 is the first validator.
|
||||
// 1.1 adds:
|
||||
// - ILDN container part support
|
||||
*pMajor = 1;
|
||||
*pMinor = 1;
|
||||
}
|
||||
|
@ -4334,6 +4336,7 @@ HRESULT ValidateDxilContainerParts(llvm::Module *pModule,
|
|||
case DFCC_PrivateData:
|
||||
case DFCC_DXIL:
|
||||
case DFCC_ShaderDebugInfoDXIL:
|
||||
case DFCC_ShaderDebugName:
|
||||
continue;
|
||||
|
||||
case DFCC_Container:
|
||||
|
|
|
@ -78,6 +78,7 @@ private:
|
|||
DxcDllSupport &m_dxcSupport;
|
||||
|
||||
int ActOnBlob(IDxcBlob *pBlob);
|
||||
int ActOnBlob(IDxcBlob *pBlob, IDxcBlob *pDebugBlob, LPCWSTR pDebugBlobName);
|
||||
void UpdatePart(IDxcBlob *pBlob, IDxcBlob **ppResult);
|
||||
bool UpdatePartRequired();
|
||||
void WriteHeader(IDxcBlobEncoding *pDisassembly, IDxcBlob *pCode,
|
||||
|
@ -135,6 +136,10 @@ static void WritePartToFile(IDxcBlob *pBlob, hlsl::DxilFourCC CC,
|
|||
// This function is called either after the compilation is done or /dumpbin option is provided
|
||||
// Performing options that are used to process dxil container.
|
||||
int DxcContext::ActOnBlob(IDxcBlob *pBlob) {
|
||||
return ActOnBlob(pBlob, nullptr, nullptr);
|
||||
}
|
||||
|
||||
int DxcContext::ActOnBlob(IDxcBlob *pBlob, IDxcBlob *pDebugBlob, LPCWSTR pDebugBlobName) {
|
||||
int retVal = 0;
|
||||
// Text output.
|
||||
if (m_Opts.AstDump || m_Opts.OptDump) {
|
||||
|
@ -164,8 +169,15 @@ int DxcContext::ActOnBlob(IDxcBlob *pBlob) {
|
|||
"/Zi switch to generate debug "
|
||||
"information compiling this shader.");
|
||||
|
||||
if (pDebugBlob != nullptr) {
|
||||
IFTBOOLMSG(pDebugBlobName && *pDebugBlobName, E_INVALIDARG,
|
||||
"/Fd was specified but no debug name was produced");
|
||||
WriteBlobToFile(pDebugBlob, pDebugBlobName);
|
||||
}
|
||||
else {
|
||||
WritePartToFile(pBlob, hlsl::DFCC_ShaderDebugInfoDXIL, m_Opts.DebugFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract and write root signature information.
|
||||
if (m_Opts.ExtractRootSignature) {
|
||||
|
@ -598,6 +610,8 @@ void DxcContext::Recompile(IDxcBlob *pSource, IDxcLibrary *pLibrary, IDxcCompile
|
|||
int DxcContext::Compile() {
|
||||
CComPtr<IDxcCompiler> pCompiler;
|
||||
CComPtr<IDxcOperationResult> pCompileResult;
|
||||
CComPtr<IDxcBlob> pDebugBlob;
|
||||
std::wstring debugName;
|
||||
{
|
||||
CComPtr<IDxcBlobEncoding> pSource;
|
||||
|
||||
|
@ -632,6 +646,22 @@ int DxcContext::Compile() {
|
|||
TargetProfile = hlsl::ShaderModel::Get(SM->GetKind(), 6, 0)->GetName();
|
||||
}
|
||||
|
||||
if (!m_Opts.DebugFile.empty() && m_Opts.DebugFile.endswith(llvm::StringRef("\\"))) {
|
||||
args.push_back(L"/Qstrip_debug"); // implied
|
||||
CComPtr<IDxcCompiler2> pCompiler2;
|
||||
CComHeapPtr<WCHAR> pDebugName;
|
||||
IFT(pCompiler.QueryInterface(&pCompiler2));
|
||||
IFT(pCompiler2->CompileWithDebug(
|
||||
pSource, StringRefUtf16(m_Opts.InputFile),
|
||||
StringRefUtf16(m_Opts.EntryPoint), StringRefUtf16(TargetProfile),
|
||||
args.data(), args.size(), m_Opts.Defines.data(),
|
||||
m_Opts.Defines.size(), pIncludeHandler, &pCompileResult,
|
||||
&pDebugName, &pDebugBlob));
|
||||
if (pDebugName.m_pData) {
|
||||
Unicode::UTF8ToUTF16String(m_Opts.DebugFile.str().c_str(), &debugName);
|
||||
debugName += pDebugName.m_pData;
|
||||
}
|
||||
} else {
|
||||
IFT(pCompiler->Compile(pSource, StringRefUtf16(m_Opts.InputFile),
|
||||
StringRefUtf16(m_Opts.EntryPoint),
|
||||
StringRefUtf16(TargetProfile), args.data(),
|
||||
|
@ -639,6 +669,7 @@ int DxcContext::Compile() {
|
|||
m_Opts.Defines.size(), pIncludeHandler, &pCompileResult));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_Opts.OutputWarningsFile.empty()) {
|
||||
CComPtr<IDxcBlobEncoding> pErrors;
|
||||
|
@ -657,7 +688,7 @@ int DxcContext::Compile() {
|
|||
pCompiler.Release();
|
||||
pCompileResult.Release();
|
||||
if (pProgram.p != nullptr) {
|
||||
ActOnBlob(pProgram.p);
|
||||
ActOnBlob(pProgram.p, pDebugBlob, debugName.c_str());
|
||||
}
|
||||
}
|
||||
return status;
|
||||
|
|
|
@ -121,7 +121,9 @@ HRESULT STDMETHODCALLTYPE DxcAssembler::AssembleToContainer(
|
|||
CComPtr<AbstractMemoryStream> pFinalStream;
|
||||
IFT(CreateMemoryStream(pMalloc, &pFinalStream));
|
||||
|
||||
SerializeDxilContainerForModule(&M->GetOrCreateDxilModule(), pOutputStream, pFinalStream);
|
||||
SerializeDxilContainerForModule(&M->GetOrCreateDxilModule(), pOutputStream,
|
||||
pFinalStream,
|
||||
SerializeDxilFlags::IncludeDebugNamePart);
|
||||
|
||||
CComPtr<IDxcBlob> pResultBlob;
|
||||
IFT(pFinalStream->QueryInterface(&pResultBlob));
|
||||
|
|
|
@ -120,6 +120,21 @@ HRESULT RunInternalValidator(_In_ IDxcValidator *pValidator,
|
|||
_In_ IDxcBlob *pShader, UINT32 Flags,
|
||||
_In_ IDxcOperationResult **ppResult);
|
||||
|
||||
static HRESULT GetValidatorVersion(IDxcValidator *pValidator, UINT32 *pMajor,
|
||||
UINT32 *pMinor) {
|
||||
CComPtr<IDxcVersionInfo> pVersionInfo;
|
||||
IFR(pValidator->QueryInterface(&pVersionInfo));
|
||||
IFR(pVersionInfo->GetVersion(pMajor, pMinor));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static bool DoesValidatorSupportDebugNamePart(IDxcValidator *pValidator) {
|
||||
UINT32 Major, Minor;
|
||||
if (FAILED((GetValidatorVersion(pValidator, &Major, &Minor))))
|
||||
return false;
|
||||
return Major > 1 || (Major == 1 && Minor >= 1);
|
||||
}
|
||||
|
||||
enum class HandleKind {
|
||||
Special = 0,
|
||||
File = 1,
|
||||
|
@ -1952,10 +1967,14 @@ public:
|
|||
m_llvmModuleWithDebugInfo.reset(llvm::CloneModule(m_llvmModule.get()));
|
||||
}
|
||||
|
||||
void WrapModuleInDxilContainer(IMalloc *pMalloc, AbstractMemoryStream *pModuleBitcode, CComPtr<IDxcBlob> &pDxilContainerBlob) {
|
||||
void WrapModuleInDxilContainer(IMalloc *pMalloc,
|
||||
AbstractMemoryStream *pModuleBitcode,
|
||||
CComPtr<IDxcBlob> &pDxilContainerBlob,
|
||||
SerializeDxilFlags Flags) {
|
||||
CComPtr<AbstractMemoryStream> pContainerStream;
|
||||
IFT(CreateMemoryStream(pMalloc, &pContainerStream));
|
||||
SerializeDxilContainerForModule(&m_llvmModule->GetOrCreateDxilModule(), pModuleBitcode, pContainerStream);
|
||||
SerializeDxilContainerForModule(&m_llvmModule->GetOrCreateDxilModule(),
|
||||
pModuleBitcode, pContainerStream, Flags);
|
||||
|
||||
pDxilContainerBlob.Release();
|
||||
IFT(pContainerStream.QueryInterface(&pDxilContainerBlob));
|
||||
|
@ -1969,7 +1988,7 @@ private:
|
|||
std::unique_ptr<llvm::Module> m_llvmModuleWithDebugInfo;
|
||||
};
|
||||
|
||||
class DxcCompiler : public IDxcCompiler, public IDxcLangExtensions, public IDxcContainerEvent, public IDxcVersionInfo {
|
||||
class DxcCompiler : public IDxcCompiler2, public IDxcLangExtensions, public IDxcContainerEvent, public IDxcVersionInfo {
|
||||
private:
|
||||
DXC_MICROCOM_REF_FIELD(m_dwRef)
|
||||
DxcLangExtensionsHelper m_langExtensionsHelper;
|
||||
|
@ -2028,7 +2047,7 @@ public:
|
|||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) {
|
||||
return DoBasicQueryInterface4<IDxcCompiler, IDxcLangExtensions, IDxcContainerEvent, IDxcVersionInfo>(this, iid, ppvObject);
|
||||
return DoBasicQueryInterface5<IDxcCompiler, IDxcCompiler2, IDxcLangExtensions, IDxcContainerEvent, IDxcVersionInfo>(this, iid, ppvObject);
|
||||
}
|
||||
|
||||
// Compile a single entry point to the target shader model
|
||||
|
@ -2043,6 +2062,26 @@ public:
|
|||
_In_ UINT32 defineCount, // Number of defines
|
||||
_In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional)
|
||||
_COM_Outptr_ IDxcOperationResult **ppResult // Compiler output status, buffer, and errors
|
||||
) {
|
||||
return CompileWithDebug(pSource, pSourceName, pEntryPoint, pTargetProfile,
|
||||
pArguments, argCount, pDefines, defineCount,
|
||||
pIncludeHandler, ppResult, nullptr, nullptr);
|
||||
}
|
||||
|
||||
// Compile a single entry point to the target shader model with debug information.
|
||||
__override HRESULT STDMETHODCALLTYPE CompileWithDebug(
|
||||
_In_ IDxcBlob *pSource, // Source text to compile
|
||||
_In_opt_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers.
|
||||
_In_ LPCWSTR pEntryPoint, // Entry point name
|
||||
_In_ LPCWSTR pTargetProfile, // Shader profile to compile
|
||||
_In_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments
|
||||
_In_ UINT32 argCount, // Number of arguments
|
||||
_In_count_(defineCount) const DxcDefine *pDefines, // Array of defines
|
||||
_In_ UINT32 defineCount, // Number of defines
|
||||
_In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional)
|
||||
_COM_Outptr_ IDxcOperationResult **ppResult, // Compiler output status, buffer, and errors
|
||||
_Outptr_opt_result_z_ LPWSTR *ppDebugBlobName,// Suggested file name for debug blob.
|
||||
_COM_Outptr_opt_ IDxcBlob **ppDebugBlob // Debug blob
|
||||
) {
|
||||
if (pSource == nullptr || ppResult == nullptr ||
|
||||
(defineCount > 0 && pDefines == nullptr) ||
|
||||
|
@ -2050,15 +2089,18 @@ public:
|
|||
pTargetProfile == nullptr)
|
||||
return E_INVALIDARG;
|
||||
*ppResult = nullptr;
|
||||
AssignToOutOpt(nullptr, ppDebugBlobName);
|
||||
AssignToOutOpt(nullptr, ppDebugBlob);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
CComPtr<IDxcBlobEncoding> utf8Source;
|
||||
CComPtr<AbstractMemoryStream> pOutputStream;
|
||||
CHeapPtr<wchar_t> DebugBlobName;
|
||||
DxcEtw_DXCompilerCompile_Start();
|
||||
IFC(hlsl::DxcGetBlobAsUtf8(pSource, &utf8Source));
|
||||
|
||||
try {
|
||||
CComPtr<IMalloc> pMalloc;
|
||||
CComPtr<AbstractMemoryStream> pOutputStream;
|
||||
CComPtr<IDxcBlob> pOutputBlob;
|
||||
DxcArgsFileSystem *msfPtr;
|
||||
IFT(CreateDxcArgsFileSystem(utf8Source, pSourceName, pIncludeHandler, &msfPtr));
|
||||
|
@ -2149,7 +2191,8 @@ public:
|
|||
|
||||
// NOTE: this calls the validation component from dxil.dll; the built-in
|
||||
// validator can be used as a fallback.
|
||||
bool needsValidation = !opts.CodeGenHighLevel && !opts.DisableValidation;
|
||||
bool produceFullContainer = !opts.CodeGenHighLevel && !opts.AstDump && !opts.OptDump && rootSigMajor == 0;
|
||||
bool needsValidation = produceFullContainer && !opts.DisableValidation;
|
||||
bool internalValidator = false;
|
||||
CComPtr<IDxcValidator> pValidator;
|
||||
CComPtr<IDxcOperationResult> pValResult;
|
||||
|
@ -2241,6 +2284,19 @@ public:
|
|||
}
|
||||
outStream.flush();
|
||||
|
||||
SerializeDxilFlags SerializeFlags = SerializeDxilFlags::None;
|
||||
if (opts.DebugInfo) {
|
||||
if (DoesValidatorSupportDebugNamePart(pValidator))
|
||||
SerializeFlags = SerializeDxilFlags::IncludeDebugNamePart;
|
||||
// Unless we want to strip it right away, include it in the container.
|
||||
if (!opts.StripDebug || ppDebugBlob == nullptr) {
|
||||
SerializeFlags |= SerializeDxilFlags::IncludeDebugInfoPart;
|
||||
}
|
||||
}
|
||||
if (opts.DebugNameForSource) {
|
||||
SerializeFlags |= SerializeDxilFlags::DebugNameDependOnSource;
|
||||
}
|
||||
|
||||
// Don't do work to put in a container if an error has occurred
|
||||
if (compileOK) {
|
||||
HRESULT valHR = S_OK;
|
||||
|
@ -2257,7 +2313,7 @@ public:
|
|||
|
||||
// Do not create a container when there is only a a high-level representation in the module.
|
||||
if (!opts.CodeGenHighLevel)
|
||||
llvmModule.WrapModuleInDxilContainer(pMalloc, pOutputStream, pOutputBlob);
|
||||
llvmModule.WrapModuleInDxilContainer(pMalloc, pOutputStream, pOutputBlob, SerializeFlags);
|
||||
|
||||
if (needsValidation) {
|
||||
// Important: in-place edit is required so the blob is reused and thus
|
||||
|
@ -2291,6 +2347,7 @@ public:
|
|||
}
|
||||
pValidator.Release();
|
||||
}
|
||||
|
||||
// Callback after valid DXIL is produced
|
||||
if (SUCCEEDED(valHR)) {
|
||||
CComPtr<IDxcBlob> pTargetBlob;
|
||||
|
@ -2300,6 +2357,19 @@ public:
|
|||
std::swap(pOutputBlob, pTargetBlob);
|
||||
}
|
||||
}
|
||||
|
||||
if (ppDebugBlobName && produceFullContainer) {
|
||||
const DxilContainerHeader *pContainer = reinterpret_cast<DxilContainerHeader *>(pOutputBlob->GetBufferPointer());
|
||||
DXASSERT(IsValidDxilContainer(pContainer, pOutputBlob->GetBufferSize()), "else invalid container generated");
|
||||
auto it = std::find_if(begin(pContainer), end(pContainer),
|
||||
DxilPartIsType(DFCC_ShaderDebugName));
|
||||
if (it != end(pContainer)) {
|
||||
const char *pDebugName;
|
||||
if (GetDxilShaderDebugName(*it, &pDebugName, nullptr) && pDebugName && *pDebugName) {
|
||||
IFTBOOL(Unicode::UTF8BufferToUTF16ComHeap(pDebugName, &DebugBlobName), DXC_E_CONTAINER_INVALID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2309,6 +2379,19 @@ public:
|
|||
|
||||
CreateOperationResultFromOutputs(pOutputBlob, msfPtr, warnings,
|
||||
compiler.getDiagnostics(), ppResult);
|
||||
|
||||
// On success, return values. After assigning ppResult, nothing should fail.
|
||||
HRESULT status;
|
||||
DXVERIFY_NOMSG(SUCCEEDED((*ppResult)->GetStatus(&status)));
|
||||
if (SUCCEEDED(status)) {
|
||||
if (opts.DebugInfo && ppDebugBlob) {
|
||||
DXVERIFY_NOMSG(SUCCEEDED(pOutputStream.QueryInterface(ppDebugBlob)));
|
||||
}
|
||||
if (ppDebugBlobName) {
|
||||
*ppDebugBlobName = DebugBlobName.Detach();
|
||||
}
|
||||
}
|
||||
|
||||
hr = S_OK;
|
||||
}
|
||||
CATCH_CPP_ASSIGN_HRESULT();
|
||||
|
@ -2501,6 +2584,18 @@ public:
|
|||
Stream, /*comment*/";");
|
||||
}
|
||||
|
||||
it = std::find_if(begin(pContainer), end(pContainer),
|
||||
DxilPartIsType(DFCC_ShaderDebugName));
|
||||
if (it != end(pContainer)) {
|
||||
const char *pDebugName;
|
||||
if (!GetDxilShaderDebugName(*it, &pDebugName, nullptr)) {
|
||||
Stream << "; shader debug name present; corruption detected\n";
|
||||
}
|
||||
else if (pDebugName && *pDebugName) {
|
||||
Stream << "; shader debug name: " << pDebugName << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
it = std::find_if(begin(pContainer), end(pContainer),
|
||||
DxilPartIsType(DFCC_DXIL));
|
||||
if (it == end(pContainer)) {
|
||||
|
@ -2673,9 +2768,12 @@ public:
|
|||
else
|
||||
compiler.getCodeGenOpts().HLSLSignaturePackingStrategy = (unsigned)DXIL::PackingStrategy::Default;
|
||||
|
||||
// Constructing vector of wide strings to pass in to codegen. Just passing in pArguments will expose ownership of memory to both CodeGenOptions and this caller, which can lead to unexpected behavior.
|
||||
// Constructing vector of wide strings to pass in to codegen. Just passing
|
||||
// in pArguments will expose ownership of memory to both CodeGenOptions and
|
||||
// this caller, which can lead to unexpected behavior.
|
||||
for (UINT32 i = 0; i != argCount; ++i) {
|
||||
compiler.getCodeGenOpts().HLSLArguments.emplace_back(Unicode::UTF16ToUTF8StringOrThrow(pArguments[i]));
|
||||
compiler.getCodeGenOpts().HLSLArguments.emplace_back(
|
||||
Unicode::UTF16ToUTF8StringOrThrow(pArguments[i]));
|
||||
}
|
||||
// Overrding default set of loop unroll.
|
||||
if (Opts.PreferFlowControl)
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
TEST_METHOD_PROPERTY(L"Priority", L"0")
|
||||
END_TEST_CLASS()
|
||||
|
||||
TEST_METHOD(CompileWhenDebugSourceThenSourceMatters)
|
||||
TEST_METHOD(CompileWhenOKThenIncludesFeatureInfo)
|
||||
TEST_METHOD(CompileWhenOKThenIncludesSignatures)
|
||||
TEST_METHOD(CompileWhenSigSquareThenIncludeSplit)
|
||||
|
@ -407,20 +408,59 @@ public:
|
|||
__uuidof(ID3D12ShaderReflection), (void **)ppReflection));
|
||||
}
|
||||
|
||||
std::string DisassembleProgram(LPCSTR program, LPCWSTR entryPoint,
|
||||
LPCWSTR target) {
|
||||
void CompileToProgram(LPCSTR program, LPCWSTR entryPoint, LPCWSTR target,
|
||||
LPCWSTR *pArguments, UINT32 argCount,
|
||||
IDxcBlob **ppProgram) {
|
||||
CComPtr<IDxcCompiler> pCompiler;
|
||||
CComPtr<IDxcBlobEncoding> pSource;
|
||||
CComPtr<IDxcBlob> pProgram;
|
||||
CComPtr<IDxcBlobEncoding> pDisassembly;
|
||||
CComPtr<IDxcOperationResult> pResult;
|
||||
|
||||
VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
|
||||
CreateBlobFromText(program, &pSource);
|
||||
VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", entryPoint,
|
||||
target, nullptr, 0, nullptr, 0, nullptr,
|
||||
&pResult));
|
||||
target, pArguments, argCount, nullptr,
|
||||
0, nullptr, &pResult));
|
||||
VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
|
||||
*ppProgram = pProgram.Detach();
|
||||
}
|
||||
|
||||
bool DoesValidatorSupportDebugName() {
|
||||
CComPtr<IDxcVersionInfo> pVersionInfo;
|
||||
UINT Major, Minor;
|
||||
HRESULT hrVer = m_dllSupport.CreateInstance(CLSID_DxcValidator, &pVersionInfo);
|
||||
if (hrVer == E_NOINTERFACE) return false;
|
||||
VERIFY_SUCCEEDED(hrVer);
|
||||
VERIFY_SUCCEEDED(pVersionInfo->GetVersion(&Major, &Minor));
|
||||
return Major == 1 && (Minor >= 1);
|
||||
}
|
||||
|
||||
std::string CompileToDebugName(LPCSTR program, LPCWSTR entryPoint,
|
||||
LPCWSTR target, LPCWSTR *pArguments, UINT32 argCount) {
|
||||
CComPtr<IDxcBlob> pProgram;
|
||||
CComPtr<IDxcBlob> pNameBlob;
|
||||
CComPtr<IDxcContainerReflection> pContainer;
|
||||
UINT32 index;
|
||||
|
||||
CompileToProgram(program, entryPoint, target, pArguments, argCount, &pProgram);
|
||||
VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcContainerReflection, &pContainer));
|
||||
VERIFY_SUCCEEDED(pContainer->Load(pProgram));
|
||||
if (FAILED(pContainer->FindFirstPartKind(hlsl::DFCC_ShaderDebugName, &index))) {
|
||||
return std::string();
|
||||
}
|
||||
VERIFY_SUCCEEDED(pContainer->GetPartContent(index, &pNameBlob));
|
||||
const hlsl::DxilShaderDebugName *pDebugName = (hlsl::DxilShaderDebugName *)pNameBlob->GetBufferPointer();
|
||||
return std::string((const char *)(pDebugName + 1));
|
||||
}
|
||||
|
||||
std::string DisassembleProgram(LPCSTR program, LPCWSTR entryPoint,
|
||||
LPCWSTR target) {
|
||||
CComPtr<IDxcCompiler> pCompiler;
|
||||
CComPtr<IDxcBlob> pProgram;
|
||||
CComPtr<IDxcBlobEncoding> pDisassembly;
|
||||
|
||||
CompileToProgram(program, entryPoint, target, nullptr, 0, &pProgram);
|
||||
VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
|
||||
VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
|
||||
return BlobToUtf8(pDisassembly);
|
||||
}
|
||||
|
@ -481,6 +521,43 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
TEST_F(DxilContainerTest, CompileWhenDebugSourceThenSourceMatters) {
|
||||
char program1[] = "float4 main() : SV_Target { return 0; }";
|
||||
char program2[] = " float4 main() : SV_Target { return 0; } ";
|
||||
LPCWSTR Zi[] = { L"/Zi" };
|
||||
LPCWSTR ZiZss[] = { L"/Zi", L"/Zss" };
|
||||
LPCWSTR ZiZsb[] = { L"/Zi", L"/Zsb" };
|
||||
|
||||
// No debug info, no debug name...
|
||||
std::string noName = CompileToDebugName(program1, L"main", L"ps_6_0", nullptr, 0);
|
||||
VERIFY_IS_TRUE(noName.empty());
|
||||
|
||||
if (!DoesValidatorSupportDebugName())
|
||||
return;
|
||||
|
||||
// Debug info, default to source name.
|
||||
std::string sourceName1 = CompileToDebugName(program1, L"main", L"ps_6_0", Zi, _countof(Zi));
|
||||
VERIFY_IS_FALSE(sourceName1.empty());
|
||||
|
||||
// Deterministic naming.
|
||||
std::string sourceName1Again = CompileToDebugName(program1, L"main", L"ps_6_0", Zi, _countof(Zi));
|
||||
VERIFY_ARE_EQUAL_STR(sourceName1.c_str(), sourceName1Again.c_str());
|
||||
|
||||
// Changes in source become changes in name.
|
||||
std::string sourceName2 = CompileToDebugName(program2, L"main", L"ps_6_0", Zi, _countof(Zi));
|
||||
VERIFY_IS_FALSE(0 == strcmp(sourceName2.c_str(), sourceName1.c_str()));
|
||||
|
||||
// Source again, different because different switches are specified.
|
||||
std::string sourceName1Zss = CompileToDebugName(program1, L"main", L"ps_6_0", ZiZss, _countof(ZiZss));
|
||||
VERIFY_IS_FALSE(0 == strcmp(sourceName1Zss.c_str(), sourceName1.c_str()));
|
||||
|
||||
// Binary program 1 and 2 should be different from source and equal to each other.
|
||||
std::string binName1 = CompileToDebugName(program1, L"main", L"ps_6_0", ZiZsb, _countof(ZiZsb));
|
||||
std::string binName2 = CompileToDebugName(program2, L"main", L"ps_6_0", ZiZsb, _countof(ZiZsb));
|
||||
VERIFY_ARE_EQUAL_STR(binName1.c_str(), binName2.c_str());
|
||||
VERIFY_IS_FALSE(0 == strcmp(sourceName1Zss.c_str(), binName1.c_str()));
|
||||
}
|
||||
|
||||
TEST_F(DxilContainerTest, CompileWhenOKThenIncludesSignatures) {
|
||||
char program[] =
|
||||
"struct PSInput {\r\n"
|
||||
|
|
|
@ -819,7 +819,10 @@ def get_opcodes_rst():
|
|||
rows = []
|
||||
rows.append(["ID", "Name", "Description"])
|
||||
for i in instrs:
|
||||
rows.append([i.dxil_opid, i.dxil_op + "_", i.doc]) #append _ to enable internal hyperlink on rst files
|
||||
op_name = i.dxil_op
|
||||
if i.remarks:
|
||||
op_name = op_name + "_" # append _ to enable internal hyperlink on rst files
|
||||
rows.append([i.dxil_opid, op_name, i.doc])
|
||||
result = "\n\n" + format_rst_table(rows) + "\n\n"
|
||||
# Add detailed instruction information where available.
|
||||
instrs = sorted(instrs, key=lambda v : v.name)
|
||||
|
|
|
@ -38,6 +38,40 @@ if %errorlevel% neq 0 (
|
|||
exit /b 1
|
||||
)
|
||||
|
||||
rem When dxil.dll is present, /Fd with trailing will not produce a name.
|
||||
if exist dxil.dll (
|
||||
echo Skipping /Fd with trailing backslash when dxil.dll is present.
|
||||
echo A future dxil.dll will provide this information.
|
||||
goto :skipfdtrail
|
||||
)
|
||||
dxc.exe /T ps_6_0 smoke.hlsl /Zi /Fd %CD%\ /Fo smoke.hlsl.strip 1>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo Failed - %CD%\dxc.exe /T ps_6_0 smoke.hlsl /Zi /Fd %CD%\
|
||||
call :cleanup 2>nul
|
||||
exit /b 1
|
||||
)
|
||||
rem .lld file should be produced
|
||||
dir %CD%\*.lld 1>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo Failed to find some .lld file at %CD%
|
||||
call :cleanup 2>nul
|
||||
exit /b 1
|
||||
)
|
||||
rem /Fd with trailing backslash implies /Qstrip_debug
|
||||
dxc.exe -dumpbin smoke.hlsl.strip | findstr "shader debug name" 1>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo Failed to find shader debug name.
|
||||
call :cleanup 2>nul
|
||||
exit /b 1
|
||||
)
|
||||
dxc.exe -dumpbin smoke.hlsl.strip | findstr "DICompileUnit" 1>nul
|
||||
if %errorlevel% equ 0 (
|
||||
echo Found DICompileUnit after implied strip.
|
||||
call :cleanup 2>nul
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:skipfdtrail
|
||||
dxc.exe /T ps_6_0 smoke.hlsl /Fe smoke.hlsl.e 1>nul
|
||||
if %errorlevel% neq 0 (
|
||||
echo Failed - %CD%\dxc.exe /T ps_6_0 smoke.hlsl /Fe %CD%\smoke.hlsl.e
|
||||
|
@ -435,6 +469,9 @@ if %errorlevel% neq 0 (
|
|||
exit /b 1
|
||||
)
|
||||
|
||||
echo Smoke test for debug info extraction.
|
||||
dxc.exe smoke.hlsl
|
||||
|
||||
call :cleanup
|
||||
exit /b 0
|
||||
|
||||
|
@ -444,6 +481,7 @@ del %CD%\smoke.hlsl.c
|
|||
del %CD%\smoke.hlsl.d
|
||||
del %CD%\smoke.hlsl.e
|
||||
del %CD%\smoke.hlsl.h
|
||||
del %CD%\smoke.hlsl.strip
|
||||
del %CD%\smoke.cso
|
||||
del %CD%\NonUniform.cso
|
||||
del %CD%\private.cso
|
||||
|
@ -459,6 +497,7 @@ del %CD%\NonUniformNoRootSig.cso
|
|||
del %CD%\TextVS.cso
|
||||
del %CD%\smoke.ll
|
||||
del %CD%\smoke.cso.ll
|
||||
del %CD%\*.lld
|
||||
del %CD%\smoke.cso.plain.bc
|
||||
del %CD%\smoke.rebuilt-container.cso
|
||||
del %CD%\smoke.rebuilt-container2.cso
|
||||
|
|
|
@ -16,13 +16,12 @@ if not exist "%HLSL_BLD_DIR%\LLVM.sln" (
|
|||
)
|
||||
|
||||
if not exist "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe" (
|
||||
echo Missing Visual Studio at "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe"
|
||||
exit /b 1
|
||||
start %HLSL_BLD_DIR%\LLVM.sln
|
||||
) else (
|
||||
start "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe" %HLSL_BLD_DIR%\LLVM.sln
|
||||
)
|
||||
|
||||
start "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe" %HLSL_BLD_DIR%\LLVM.sln
|
||||
|
||||
exit /b 0
|
||||
goto :eof
|
||||
|
||||
:showhelp
|
||||
echo Launches Visual Studio and opens the solution file.
|
||||
|
|
Загрузка…
Ссылка в новой задаче