summaryrefslogtreecommitdiffstats
path: root/Graphics/ShaderTools
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2021-02-05 21:35:37 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:31:35 +0000
commit78fa6c94992a6d1a140da1354448a004e62c9683 (patch)
treec21183a39d58ba9ccc89d9d8ea6fe1aa9de2ec35 /Graphics/ShaderTools
parentMerged master (diff)
downloadDiligentCore-78fa6c94992a6d1a140da1354448a004e62c9683.tar.gz
DiligentCore-78fa6c94992a6d1a140da1354448a004e62c9683.zip
merged with resource_signature
Diffstat (limited to 'Graphics/ShaderTools')
-rw-r--r--Graphics/ShaderTools/include/DXBCUtils.hpp26
-rw-r--r--Graphics/ShaderTools/include/DXCompiler.hpp8
-rw-r--r--Graphics/ShaderTools/include/ResourceBindingMap.hpp61
-rw-r--r--Graphics/ShaderTools/src/DXBCUtils.cpp6
-rw-r--r--Graphics/ShaderTools/src/DXCompiler.cpp210
5 files changed, 284 insertions, 27 deletions
diff --git a/Graphics/ShaderTools/include/DXBCUtils.hpp b/Graphics/ShaderTools/include/DXBCUtils.hpp
index bb509908..20d26547 100644
--- a/Graphics/ShaderTools/include/DXBCUtils.hpp
+++ b/Graphics/ShaderTools/include/DXBCUtils.hpp
@@ -27,35 +27,29 @@
#pragma once
-#include <unordered_map>
+#include <d3dcommon.h>
-#include "BasicTypes.h"
-#include "HashUtils.hpp"
+#include "Constants.h"
+#include "Shader.h"
+#include "ResourceBindingMap.hpp"
namespace Diligent
{
struct DXBCUtils
{
- struct BindInfo
- {
- Uint32 BindPoint = ~0u;
- Uint32 Space = ~0u;
- };
-
- /// A mapping from the resource name to the binding (shader register).
- using TResourceBindingMap = std::unordered_map<HashMapStringKey, BindInfo, HashMapStringKey::Hasher>;
+ using BindInfo = ResourceBinding::BindInfo;
+ using TResourceBindingMap = ResourceBinding::TMap;
/// Remaps resource bindings in the given DXBC byte code.
/// \param [in] ResourceMap - Resource binding map. For every resource in the
/// byte code it must define the binding (shader register).
- /// \param [inout] pBytecode - Pointer to the byte code to be patched.
- /// \param [in] Size - The byte code size, in bytes.
- static bool RemapDXBCResources(const TResourceBindingMap& ResourceMap,
- void* pBytecode,
- size_t Size);
+ /// \param [inout] pBytecode - Byte code that will be patched.
+ static bool RemapResourceBindings(const TResourceBindingMap& ResourceMap,
+ void* pBytecode,
+ size_t Size);
};
} // namespace Diligent
diff --git a/Graphics/ShaderTools/include/DXCompiler.hpp b/Graphics/ShaderTools/include/DXCompiler.hpp
index 4f1a4d1b..d373292d 100644
--- a/Graphics/ShaderTools/include/DXCompiler.hpp
+++ b/Graphics/ShaderTools/include/DXCompiler.hpp
@@ -29,13 +29,12 @@
#include <array>
#include <vector>
-#include <unordered_map>
#include <memory>
#include "Constants.h"
#include "Shader.h"
#include "DataBlob.h"
-#include "HashUtils.hpp"
+#include "ResourceBindingMap.hpp"
// defined in dxcapi.h
struct DxcDefine;
@@ -86,9 +85,9 @@ public:
std::vector<uint32_t>* pByteCode,
IDataBlob** ppCompilerOutput) noexcept(false) = 0;
- /// A mapping from the resource name to the binding (shader register).
- using TResourceBindingMap = std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher>;
+ using BindInfo = ResourceBinding::BindInfo;
+ using TResourceBindingMap = ResourceBinding::TMap;
/// Remaps resource bindings (shader registers) in the source byte code using the
/// resource binding map.
@@ -115,5 +114,6 @@ public:
// path is used.
std::unique_ptr<IDXCompiler> CreateDXCompiler(DXCompilerTarget Target, const char* pLibraryName);
+bool IsDXILBytecode(const void* pBytecode, size_t Size);
} // namespace Diligent
diff --git a/Graphics/ShaderTools/include/ResourceBindingMap.hpp b/Graphics/ShaderTools/include/ResourceBindingMap.hpp
new file mode 100644
index 00000000..b334b890
--- /dev/null
+++ b/Graphics/ShaderTools/include/ResourceBindingMap.hpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019-2021 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <unordered_map>
+
+#include "Constants.h"
+#include "HashUtils.hpp"
+
+namespace Diligent
+{
+
+struct ResourceBinding
+{
+ struct BindInfo
+ {
+ // new bind point & space
+ Uint32 BindPoint = ~0u;
+ Uint32 Space = ~0u;
+
+ // current (previous) bind point & space
+ mutable Uint32 SrcBindPoint = ~0u;
+ mutable Uint32 SrcSpace = ~0u;
+
+ BindInfo() {}
+
+ BindInfo(Uint32 _BindPoint, Uint32 _Space) :
+ BindPoint{_BindPoint}, Space{_Space}
+ {}
+ };
+
+ /// A mapping from the resource name to the binding (shader register).
+ using TMap = std::unordered_map<HashMapStringKey, BindInfo, HashMapStringKey::Hasher>;
+};
+
+} // namespace Diligent
diff --git a/Graphics/ShaderTools/src/DXBCUtils.cpp b/Graphics/ShaderTools/src/DXBCUtils.cpp
index 08f94fb2..e65e0350 100644
--- a/Graphics/ShaderTools/src/DXBCUtils.cpp
+++ b/Graphics/ShaderTools/src/DXBCUtils.cpp
@@ -154,9 +154,9 @@ bool RemapShaderResources(const DXBCUtils::TResourceBindingMap& ResourceMap, con
} // namespace
-bool DXBCUtils::RemapDXBCResources(const TResourceBindingMap& ResourceMap,
- void* pBytecode,
- size_t Size)
+bool DXBCUtils::RemapResourceBindings(const TResourceBindingMap& ResourceMap,
+ void* pBytecode,
+ size_t Size)
{
if (pBytecode == nullptr)
{
diff --git a/Graphics/ShaderTools/src/DXCompiler.cpp b/Graphics/ShaderTools/src/DXCompiler.cpp
index 09726b43..3164e67f 100644
--- a/Graphics/ShaderTools/src/DXCompiler.cpp
+++ b/Graphics/ShaderTools/src/DXCompiler.cpp
@@ -49,6 +49,8 @@
#include "HLSLUtils.hpp"
+#include "dxc/DxilContainer/DxilContainer.h"
+
namespace Diligent
{
@@ -886,7 +888,8 @@ bool DXCompilerImpl::PatchDXIL(const TResourceBindingMap& ResourceMap, String& D
// !158 = !{i32 0, %"class.RWTexture2D<vector<float, 4> >"* @"\01?g_ColorBuffer@@3V?$RWTexture2D@V?$vector@M$03@@@@A", !"g_ColorBuffer", i32 -1, i32 -1, i32 1, i32 2, i1 false, i1 false, i1 false, !159}
const auto* Name = ResPair.first.GetStr();
- const auto& BindPoint = ResPair.second;
+ const auto Space = ResPair.second.Space;
+ const auto BindPoint = ResPair.second.BindPoint;
const auto DxilName = String{"!\""} + Name + "\"";
size_t pos = DXIL.find(DxilName);
@@ -900,7 +903,7 @@ bool DXCompilerImpl::PatchDXIL(const TResourceBindingMap& ResourceMap, String& D
// !"g_ColorBuffer", i32 -1, i32 -1,
// ^
- auto ReplaceRecord = [&](const std::string& NewValue, const char* RecordName) //
+ auto ReplaceRecord = [&](const std::string& NewValue, const char* RecordName, Uint32& PrevValue) //
{
#define CHECK_PATCHING_ERROR(Cond, ...) \
if (!(Cond)) \
@@ -940,6 +943,7 @@ bool DXCompilerImpl::PatchDXIL(const TResourceBindingMap& ResourceMap, String& D
// ^
// RecordEndPos
+ PrevValue = static_cast<Uint32>(std::stoi(DXIL.substr(pos, RecordEndPos - pos)));
DXIL.replace(pos, RecordEndPos - pos, NewValue);
// , i32 1
// ^
@@ -956,7 +960,7 @@ bool DXCompilerImpl::PatchDXIL(const TResourceBindingMap& ResourceMap, String& D
// !"g_ColorBuffer", i32 -1, i32 -1,
// ^
- if (!ReplaceRecord("0", "space"))
+ if (!ReplaceRecord(std::to_string(Space), "space", ResPair.second.SrcSpace))
{
RemappingOK = false;
continue;
@@ -964,7 +968,7 @@ bool DXCompilerImpl::PatchDXIL(const TResourceBindingMap& ResourceMap, String& D
// !"g_ColorBuffer", i32 0, i32 -1,
// ^
- if (!ReplaceRecord(std::to_string(BindPoint), "binding"))
+ if (!ReplaceRecord(std::to_string(BindPoint), "binding", ResPair.second.SrcBindPoint))
{
RemappingOK = false;
continue;
@@ -972,7 +976,205 @@ bool DXCompilerImpl::PatchDXIL(const TResourceBindingMap& ResourceMap, String& D
// !"g_ColorBuffer", i32 0, i32 1,
// ^
}
+
+ // Patch createHandle command
+ static const String CallHandlePattern = " = call %dx.types.Handle @dx.op.createHandle(";
+ static const String SamplerPart = "_sampler";
+ static const String CBufferPart = "_cbuffer";
+ static const String TexturePart = "_texture_";
+ static const String UAVPart = "_UAV_";
+
+ for (size_t startPos = 0; startPos < DXIL.size();)
+ {
+ // %dx.types.Handle @dx.op.createHandle(
+ // i32, ; opcode
+ // i8, ; resource class: SRV=0, UAV=1, CBV=2, Sampler=3
+ // i32, ; resource range ID (constant)
+ // i32, ; index into the range
+ // i1) ; non-uniform resource index: false or true
+
+ // Example:
+ //
+ // %cbConstants_cbuffer = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)
+
+ size_t callHandlePos = DXIL.find(CallHandlePattern, startPos);
+ if (callHandlePos == String::npos)
+ break;
+
+ startPos = callHandlePos + CallHandlePattern.length();
+
+ // Parse resource name: %name_suffix
+
+ size_t resNameEnd = callHandlePos;
+ size_t resNameStart = resNameEnd - 1;
+ bool partFound = false;
+ for (auto& pos = resNameStart; pos >= 0; --pos)
+ {
+ const char c = DXIL[pos];
+
+ if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
+ continue;
+
+ if (c == '_')
+ {
+ String part = DXIL.substr(pos, resNameEnd - pos);
+ if (!partFound &&
+ (part == SamplerPart || part == CBufferPart ||
+ (part.length() > TexturePart.length() && strncmp(part.c_str(), TexturePart.c_str(), TexturePart.length()) == 0) ||
+ (part.length() > UAVPart.length() && strncmp(part.c_str(), UAVPart.c_str(), UAVPart.length()) == 0)))
+ {
+ resNameEnd = pos;
+ partFound = true;
+ }
+ continue;
+ }
+
+ VERIFY_EXPR(c == '%');
+ ++pos;
+ break;
+ }
+
+ String resName = DXIL.substr(resNameStart, resNameEnd - resNameStart);
+
+ auto Iter = ResourceMap.find(HashMapStringKey{resName.c_str()});
+ if (Iter == ResourceMap.end())
+ {
+ UNEXPECTED("Resource is not exists in ResourceMap");
+ continue;
+ }
+
+ size_t pos = startPos;
+
+ const auto NextArg = [&DXIL, &pos]() {
+ ++pos;
+ for (; pos < DXIL.size(); ++pos)
+ {
+ const char c = DXIL[pos];
+ if (c == ',')
+ return true;
+ if (c == ')' || c == '\n')
+ return false;
+ }
+ return false;
+ };
+
+ // skip opcode
+ // createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)
+ // ^
+ if (!NextArg())
+ {
+ UNEXPECTED("Failed to parse createHandle()");
+ continue;
+ }
+ VERIFY_EXPR(DXIL[pos + 2] == 'i' && DXIL[pos + 3] == '8' && DXIL[pos + 4] == ' ');
+
+ // skip resource class
+ // createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)
+ // ^
+ if (!NextArg())
+ {
+ UNEXPECTED("Failed to parse createHandle()");
+ continue;
+ }
+ VERIFY_EXPR(DXIL[pos + 2] == 'i' && DXIL[pos + 3] == '3' && DXIL[pos + 4] == '2' && DXIL[pos + 5] == ' ');
+
+ // skip resource range ID
+ // createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)
+ // ^
+ if (!NextArg())
+ {
+ UNEXPECTED("Failed to parse createHandle()");
+ continue;
+ }
+ VERIFY_EXPR(DXIL[pos + 2] == 'i' && DXIL[pos + 3] == '3' && DXIL[pos + 4] == '2' && DXIL[pos + 5] == ' ');
+
+ const size_t indexStartPos = pos + 6;
+ VERIFY_EXPR(DXIL[indexStartPos] >= '0' && DXIL[indexStartPos] <= '9');
+
+ // find index end
+ // createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)
+ // ^
+ if (!NextArg())
+ {
+ UNEXPECTED("Failed to parse createHandle()");
+ continue;
+ }
+ VERIFY_EXPR(DXIL[pos + 2] == 'i' && DXIL[pos + 3] == '1' && DXIL[pos + 4] == ' ');
+
+ const size_t indexEndPos = pos;
+
+ // replace index
+ const Uint32 SrcIndex = static_cast<Uint32>(std::stoi(DXIL.substr(indexStartPos, indexEndPos - indexStartPos)));
+ VERIFY_EXPR(SrcIndex >= Iter->second.SrcBindPoint);
+ VERIFY_EXPR(Iter->second.SrcBindPoint != ~0u);
+
+ const Uint32 IndexOffset = SrcIndex - Iter->second.SrcBindPoint;
+ VERIFY_EXPR((Iter->second.BindPoint + IndexOffset) >= Iter->second.BindPoint);
+
+ const String NewIndexStr = std::to_string(Iter->second.BindPoint + IndexOffset);
+ DXIL.replace(DXIL.begin() + indexStartPos, DXIL.begin() + indexEndPos, NewIndexStr);
+
+ startPos = indexStartPos + NewIndexStr.length();
+ }
return RemappingOK;
}
+bool IsDXILBytecode(const void* pBytecode, size_t Size)
+{
+ const auto* data_begin = reinterpret_cast<const uint8_t*>(pBytecode);
+ const auto* data_end = data_begin + Size;
+ const auto* ptr = data_begin;
+
+ if (ptr + sizeof(hlsl::DxilContainerHeader) > data_end)
+ {
+ // No space for the container header
+ return false;
+ }
+
+ // A DXIL container is composed of a header, a sequence of part lengths, and a sequence of parts.
+ // https://github.com/microsoft/DirectXShaderCompiler/blob/master/docs/DXIL.rst#dxil-container-format
+ const auto& ContainerHeader = *reinterpret_cast<const hlsl::DxilContainerHeader*>(ptr);
+ if (ContainerHeader.HeaderFourCC != hlsl::DFCC_Container)
+ {
+ // Incorrect FourCC
+ return false;
+ }
+
+ if (ContainerHeader.Version.Major != hlsl::DxilContainerVersionMajor)
+ {
+ LOG_WARNING_MESSAGE("Unable to parse DXIL container: the container major version is ", Uint32{ContainerHeader.Version.Major},
+ " while ", Uint32{hlsl::DxilContainerVersionMajor}, " is expected");
+ return false;
+ }
+
+ // The header is followed by uint32_t PartOffset[PartCount];
+ // The offset is to a DxilPartHeader.
+ ptr += sizeof(hlsl::DxilContainerHeader);
+ if (ptr + sizeof(uint32_t) * ContainerHeader.PartCount > data_end)
+ {
+ // No space for offsets
+ return false;
+ }
+
+ const auto* PartOffsets = reinterpret_cast<const uint32_t*>(ptr);
+ for (uint32_t part = 0; part < ContainerHeader.PartCount; ++part)
+ {
+ const auto Offset = PartOffsets[part];
+ if (data_begin + Offset + sizeof(hlsl::DxilPartHeader) > data_end)
+ {
+ // No space for the part header
+ return false;
+ }
+
+ const auto& PartHeader = *reinterpret_cast<const hlsl::DxilPartHeader*>(data_begin + Offset);
+ if (PartHeader.PartFourCC == hlsl::DFCC_DXIL)
+ {
+ // We found DXIL part
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace Diligent