summaryrefslogtreecommitdiffstats
path: root/tools/render-test
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-10-09 11:29:11 -0700
committerGitHub <noreply@github.com>2020-10-09 11:29:11 -0700
commitfab1c9f4c745ba84983c2448646376799d461e96 (patch)
tree3176c03987417c01b7220aaf13c35b665813c876 /tools/render-test
parent11f331771a8d5d80bc1dd317dcad5eb815e9cb55 (diff)
Support CUDA bindless texture in dynamic dispatch code. (#1575)
Diffstat (limited to 'tools/render-test')
-rw-r--r--tools/render-test/cpu-compute-util.cpp150
-rw-r--r--tools/render-test/cpu-compute-util.h12
-rw-r--r--tools/render-test/cuda/cuda-compute-util.cpp134
-rw-r--r--tools/render-test/cuda/cuda-compute-util.h3
-rw-r--r--tools/render-test/render-test-main.cpp3
-rw-r--r--tools/render-test/shader-input-layout.cpp21
-rw-r--r--tools/render-test/shader-input-layout.h9
7 files changed, 289 insertions, 43 deletions
diff --git a/tools/render-test/cpu-compute-util.cpp b/tools/render-test/cpu-compute-util.cpp
index 2c9a9dc82..a861dadf3 100644
--- a/tools/render-test/cpu-compute-util.cpp
+++ b/tools/render-test/cpu-compute-util.cpp
@@ -222,13 +222,39 @@ struct FloatRWTexture : public CPUComputeUtil::Resource, public CPPPrelude::IRWT
static int _calcDims(const InputTextureDesc& desc, slang::TypeLayoutReflection* typeLayout, CPPPrelude::TextureDimensions& outDims)
{
outDims.reset();
-
- const auto kind = typeLayout->getKind();
- SLANG_ASSERT(kind == slang::TypeReflection::Kind::Resource);
-
- auto type = typeLayout->getType();
- auto shape = type->getResourceShape();
-
+ SlangResourceShape shape = SLANG_TEXTURE_2D;
+ if (typeLayout)
+ {
+ const auto kind = typeLayout->getKind();
+ SLANG_ASSERT(kind == slang::TypeReflection::Kind::Resource);
+ auto type = typeLayout->getType();
+ shape = type->getResourceShape();
+ }
+ else
+ {
+ if (desc.isCube)
+ {
+ shape = SLANG_TEXTURE_CUBE;
+ }
+ else
+ {
+ switch (desc.dimension)
+ {
+ case 1:
+ shape = SLANG_TEXTURE_1D;
+ break;
+ case 2:
+ shape = SLANG_TEXTURE_2D;
+ break;
+ case 3:
+ shape = SLANG_TEXTURE_3D;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
outDims.shape = shape;
const uint32_t size = uint32_t(desc.size);
@@ -293,26 +319,56 @@ static CPUComputeUtil::Resource* _newReadTexture(int elemCount, const CPPPrelude
static SlangResult _newTexture(const InputTextureDesc& desc, slang::TypeLayoutReflection* typeLayout, RefPtr<CPUComputeUtil::Resource>& outResource)
{
- const auto kind = typeLayout->getKind();
- SLANG_ASSERT(kind == slang::TypeReflection::Kind::Resource);
+ SlangResourceAccess access = SLANG_RESOURCE_ACCESS_READ;
+ SlangResourceShape shape = SLANG_TEXTURE_2D;
+ int elemCount = 1;
+ if (typeLayout)
+ {
+ const auto kind = typeLayout->getKind();
+ SLANG_ASSERT(kind == slang::TypeReflection::Kind::Resource);
- auto type = typeLayout->getType();
- auto shape = type->getResourceShape();
+ auto type = typeLayout->getType();
+ shape = type->getResourceShape();
- auto access = type->getResourceAccess();
+ access = type->getResourceAccess();
+ slang::TypeReflection* typeReflection = typeLayout->getResourceResultType();
+ if (typeReflection->getKind() == slang::TypeReflection::Kind::Vector)
+ {
+ elemCount = int(typeReflection->getElementCount());
+ }
+ }
+ else
+ {
+ if (desc.isCube)
+ {
+ shape = SLANG_TEXTURE_CUBE;
+ }
+ else
+ {
+ switch (desc.dimension)
+ {
+ case 1:
+ shape = SLANG_TEXTURE_1D;
+ break;
+ case 2:
+ shape = SLANG_TEXTURE_2D;
+ break;
+ case 3:
+ shape = SLANG_TEXTURE_3D;
+ break;
+ default:
+ break;
+ }
+ }
+ if (desc.isRWTexture)
+ access = SLANG_RESOURCE_ACCESS_READ_WRITE;
+ elemCount = 4;
+ }
// TODO(JS): Currently we support only textures who's content is either
// 0 or 1. This is because this is easy to implement.
// Will need to do something better in the future..
- slang::TypeReflection* typeReflection = typeLayout->getResourceResultType();
-
- int elemCount = 1;
- if (typeReflection->getKind() == slang::TypeReflection::Kind::Vector)
- {
- elemCount = int(typeReflection->getElementCount());
- }
-
float initialValue = 0.0f;
switch (desc.content)
@@ -359,8 +415,9 @@ static SlangResult _newTexture(const InputTextureDesc& desc, slang::TypeLayoutRe
return false;
}
-SlangResult CPUComputeUtil::populateRTTIEntries(
+SlangResult CPUComputeUtil::fillRuntimeHandleInBuffers(
ShaderCompilerUtil::OutputAndLayout& compilationAndLayout,
+ Context& context,
ISlangSharedLibrary* sharedLib)
{
Slang::ComPtr<slang::ISession> linkage;
@@ -418,6 +475,32 @@ SlangResult CPUComputeUtil::populateRTTIEntries(
return SLANG_FAIL;
}
}
+ for (auto& handle : entry.bindlessHandleEntry)
+ {
+ RefPtr<Resource> resource;
+ uint64_t handleValue = 0;
+ if (context.m_bindlessResources.TryGetValue(handle.name, resource))
+ {
+ handleValue = (uint64_t)resource->getInterface();
+ }
+ else
+ {
+ return SLANG_FAIL;
+ }
+ if (handle.offset >= 0 &&
+ handle.offset + sizeof(uint64_t) <=
+ entry.bufferData.getCount() * sizeof(decltype(entry.bufferData[0])))
+ {
+ memcpy(
+ ((char*)entry.bufferData.getBuffer()) + handle.offset,
+ &handleValue,
+ sizeof(handleValue));
+ }
+ else
+ {
+ return SLANG_FAIL;
+ }
+ }
}
return SLANG_OK;
}
@@ -815,5 +898,30 @@ SlangResult CPUComputeUtil::populateRTTIEntries(
return SLANG_OK;
}
+SlangResult renderer_test::CPUComputeUtil::createBindlessResources(
+ ShaderCompilerUtil::OutputAndLayout& outputAndLayout, Context& context)
+{
+ auto outStream = StdWriters::getOut();
+ for (auto& entry : outputAndLayout.layout.entries)
+ {
+ if (!entry.isBindlessObject)
+ continue;
+ switch (entry.type)
+ {
+ case ShaderInputType::Texture:
+ {
+ RefPtr<Resource> resource;
+ _newTexture(entry.textureDesc, nullptr, resource);
+ context.m_bindlessResources.Add(entry.name, resource);
+ break;
+ }
+ default:
+ outStream.print("Unsupported bindless resource type.\n");
+ return SLANG_FAIL;
+ }
+ }
+ return SLANG_OK;
+}
+
} // renderer_test
diff --git a/tools/render-test/cpu-compute-util.h b/tools/render-test/cpu-compute-util.h
index 01b781ca7..56d510818 100644
--- a/tools/render-test/cpu-compute-util.h
+++ b/tools/render-test/cpu-compute-util.h
@@ -6,7 +6,7 @@
#include "bind-location.h"
-#include "../../source/core/slang-smart-pointer.h"
+#include "../../source/core/slang-basic.h"
namespace renderer_test {
@@ -34,6 +34,9 @@ struct CPUComputeUtil
/// Buffers are held in same order as entries in layout (useful for dumping out bindings)
List<BindSet::Value*> m_buffers;
+
+ /// Bindless resource objects
+ Slang::OrderedDictionary<Slang::String, RefPtr<Resource>> m_bindlessResources;
};
struct ExecuteInfo
@@ -55,9 +58,12 @@ struct CPUComputeUtil
/// Runs code across run styles and makes sure output buffers match
static SlangResult checkStyleConsistency(ISlangSharedLibrary* sharedLib, const uint32_t dispatchSize[3], const ShaderCompilerUtil::OutputAndLayout& compilationAndLayout);
- /// Query and fill in the RTTI pointer values in data buffers.
- static SlangResult populateRTTIEntries(
+ static SlangResult createBindlessResources(ShaderCompilerUtil::OutputAndLayout& compilationAndLayout, Context& context);
+
+ /// Query and fill in the RTTI pointer and runtime resource handle values in data buffers.
+ static SlangResult fillRuntimeHandleInBuffers(
ShaderCompilerUtil::OutputAndLayout& compilationAndLayout,
+ Context& context,
ISlangSharedLibrary* sharedLib);
static SlangResult calcBindings(const ShaderCompilerUtil::OutputAndLayout& compilationAndLayout, Context& outContext);
diff --git a/tools/render-test/cuda/cuda-compute-util.cpp b/tools/render-test/cuda/cuda-compute-util.cpp
index f9e67d3f0..73ad78f0b 100644
--- a/tools/render-test/cuda/cuda-compute-util.cpp
+++ b/tools/render-test/cuda/cuda-compute-util.cpp
@@ -178,6 +178,11 @@ public:
return resource ? resource->m_cudaMemory : CUdeviceptr();
}
+ virtual uint64_t getBindlessHandle() override
+ {
+ return (uint64_t)m_cudaMemory;
+ }
+
CUdeviceptr m_cudaMemory = CUdeviceptr();
};
@@ -224,6 +229,11 @@ public:
return resource ? resource->m_cudaSurfObj : CUsurfObject(0);
}
+ virtual uint64_t getBindlessHandle() override
+ {
+ return (uint64_t)m_cudaTexObj;
+ }
+
// The texObject is for reading 'texture' like things. This is an opaque type, that's backed by a long long
CUtexObject m_cudaTexObj = CUtexObject();
@@ -537,22 +547,48 @@ static bool _hasWriteAccess(SlangResourceAccess access)
/* static */SlangResult CUDAComputeUtil::createTextureResource(const ShaderInputLayoutEntry& srcEntry, slang::TypeLayoutReflection* typeLayout, RefPtr<CUDAResource>& outResource)
{
- auto type = typeLayout->getType();
- auto shape = type->getResourceShape();
-
- auto access = type->getResourceAccess();
+ SlangResourceAccess access = SLANG_RESOURCE_ACCESS_READ;
+ SlangResourceShape baseShape = SLANG_TEXTURE_2D;
+ if (typeLayout)
+ {
+ auto type = typeLayout->getType();
+ auto shape = type->getResourceShape();
+ access = type->getResourceAccess();
- if (!(access == SLANG_RESOURCE_ACCESS_READ ||
- access == SLANG_RESOURCE_ACCESS_READ_WRITE))
+ if (!(access == SLANG_RESOURCE_ACCESS_READ || access == SLANG_RESOURCE_ACCESS_READ_WRITE))
+ {
+ SLANG_ASSERT(!"Only read or read write currently supported");
+ return SLANG_FAIL;
+ }
+ baseShape = shape & SLANG_RESOURCE_BASE_SHAPE_MASK;
+ }
+ else
{
- SLANG_ASSERT(!"Only read or read write currently supported");
- return SLANG_FAIL;
+ if (srcEntry.textureDesc.isCube)
+ {
+ baseShape = SLANG_TEXTURE_CUBE;
+ }
+ else
+ {
+ switch (srcEntry.textureDesc.dimension)
+ {
+ case 1:
+ baseShape = SLANG_TEXTURE_1D;
+ break;
+ case 2:
+ baseShape = SLANG_TEXTURE_2D;
+ break;
+ case 3:
+ baseShape = SLANG_TEXTURE_3D;
+ break;
+ default:
+ break;
+ }
+ }
+ if (srcEntry.textureDesc.isRWTexture)
+ access = SLANG_RESOURCE_ACCESS_READ_WRITE;
}
-
CUresourcetype resourceType = CU_RESOURCE_TYPE_ARRAY;
- auto baseShape = shape & SLANG_RESOURCE_BASE_SHAPE_MASK;
-
- slang::TypeReflection* typeReflection = typeLayout->getResourceResultType();
InputTextureDesc textureDesc = srcEntry.textureDesc;
@@ -1360,9 +1396,10 @@ static SlangResult _loadAndInvokeRayTracingProgram(
}
#endif
- // Fill in RTTI pointers values in input buffers.
-static SlangResult _populateRTTIEntries(
+ // Fill in runtime handles (e.g. RTTI pointers values and bindless resource handles) in input buffers.
+static SlangResult _fillRuntimeHandlesInBuffers(
const ShaderCompilerUtil::OutputAndLayout& compilationAndLayout,
+ CUDAComputeUtil::Context& context,
ScopeCUDAModule& cudaModule)
{
Slang::ComPtr<slang::ISession> linkage;
@@ -1432,6 +1469,59 @@ static SlangResult _populateRTTIEntries(
return SLANG_FAIL;
}
}
+
+ for (auto& handle : entry.bindlessHandleEntry)
+ {
+ RefPtr<CUDAResource> resource;
+ uint64_t handleValue = 0;
+ if (context.m_bindlessResources.TryGetValue(handle.name, resource))
+ {
+ handleValue = resource->getBindlessHandle();
+ }
+ else
+ {
+ return SLANG_FAIL;
+ }
+ if (handle.offset >= 0 &&
+ handle.offset + sizeof(uint64_t) <=
+ entry.bufferData.getCount() * sizeof(decltype(entry.bufferData[0])))
+ {
+ memcpy(
+ ((char*)entry.bufferData.getBuffer()) + handle.offset,
+ &handleValue,
+ sizeof(handleValue));
+ }
+ else
+ {
+ return SLANG_FAIL;
+ }
+ }
+ }
+ return SLANG_OK;
+}
+
+static SlangResult _createBindlessResources(
+ const ShaderCompilerUtil::OutputAndLayout& outputAndLayout,
+ CUDAComputeUtil::Context& outContext)
+{
+ auto outStream = StdWriters::getOut();
+ for (auto& entry : outputAndLayout.layout.entries)
+ {
+ if (!entry.isBindlessObject)
+ continue;
+ switch (entry.type)
+ {
+ case ShaderInputType::Texture:
+ {
+ RefPtr<CUDAResource> resource;
+ CUDAComputeUtil::createTextureResource(entry, nullptr, resource);
+ outContext.m_bindlessResources.Add(entry.name, resource);
+ break;
+ }
+ default:
+ outStream.print("Unsupported bindless resource type.\n");
+ return SLANG_FAIL;
+ }
}
return SLANG_OK;
}
@@ -1460,13 +1550,17 @@ static SlangResult _setUpArguments(
auto outStream = StdWriters::getOut();
- // Fill in RTTI pointers in input buffers before copying it to GPU memory.
+ _createBindlessResources(outputAndLayout, outContext);
+
+ // Fill in RTTI pointers and bindless handles in input buffers before copying
+ // it to GPU memory.
// TODO: enable this for Optix path after it is refactored so that context
// creation and module loading happens before _setUpArguments.
if (outputAndLayout.output.desc.pipelineType == PipelineType::Compute)
{
- SLANG_RETURN_ON_FAIL(_populateRTTIEntries(outputAndLayout, cudaModule));
+ SLANG_RETURN_ON_FAIL(_fillRuntimeHandlesInBuffers(outputAndLayout, outContext, cudaModule));
}
+
SLANG_RETURN_ON_FAIL(ShaderInputLayout::addBindSetValues(outputAndLayout.layout.entries, outputAndLayout.sourcePath, outStream, bindRoot));
ShaderInputLayout::getValueBuffers(outputAndLayout.layout.entries, bindSet, outContext.m_buffers);
@@ -1772,9 +1866,15 @@ SlangResult _loadAndInvokeKernel(
// Release all othe CUDA resource/allocations
bindSet.releaseValueTargets();
+ outContext.releaseBindlessResources();
return SLANG_OK;
}
-} // renderer_test
+void CUDAComputeUtil::Context::releaseBindlessResources()
+{
+ m_bindlessResources = decltype(m_bindlessResources)();
+}
+
+} // namespace renderer_test
diff --git a/tools/render-test/cuda/cuda-compute-util.h b/tools/render-test/cuda/cuda-compute-util.h
index bc3d7d233..8bc7bd8d6 100644
--- a/tools/render-test/cuda/cuda-compute-util.h
+++ b/tools/render-test/cuda/cuda-compute-util.h
@@ -13,6 +13,7 @@ namespace renderer_test {
class CUDAResource : public RefObject
{
public:
+ virtual uint64_t getBindlessHandle() = 0;
};
struct CUDAComputeUtil
@@ -44,6 +45,8 @@ struct CUDAComputeUtil
CPULikeBindRoot m_bindRoot;
/// Buffers are held in same order as entries in layout (useful for dumping out bindings)
List<BindSet::Value*> m_buffers;
+ Slang::OrderedDictionary<Slang::String, RefPtr<CUDAResource>> m_bindlessResources;
+ void releaseBindlessResources();
};
static SlangResult parseFeature(const Slang::UnownedStringSlice& feature, bool& outResult);
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp
index 42d82edf6..85e038e5a 100644
--- a/tools/render-test/render-test-main.cpp
+++ b/tools/render-test/render-test-main.cpp
@@ -650,7 +650,8 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi
// calculate binding
CPUComputeUtil::Context context;
- SLANG_RETURN_ON_FAIL(CPUComputeUtil::populateRTTIEntries(compilationAndLayout, sharedLibrary.get()));
+ SLANG_RETURN_ON_FAIL(CPUComputeUtil::createBindlessResources(compilationAndLayout, context));
+ SLANG_RETURN_ON_FAIL(CPUComputeUtil::fillRuntimeHandleInBuffers(compilationAndLayout, context, sharedLibrary.get()));
SLANG_RETURN_ON_FAIL(CPUComputeUtil::calcBindings(compilationAndLayout, context));
// Get the execution info from the lib
diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp
index 40beffc05..6ded388e8 100644
--- a/tools/render-test/shader-input-layout.cpp
+++ b/tools/render-test/shader-input-layout.cpp
@@ -432,6 +432,20 @@ namespace renderer_test
entry.bufferData.add(0);
continue;
}
+ else if (parser.LookAhead("handle"))
+ {
+ BindlessHandleDataEntry handleEntry;
+ parser.ReadToken();
+ parser.Read("(");
+ handleEntry.name = parser.ReadWord();
+ handleEntry.offset = offset;
+ parser.Read(")");
+ offset += 8;
+ entry.bindlessHandleEntry.add(handleEntry);
+ entry.bufferData.add(0);
+ entry.bufferData.add(0);
+ continue;
+ }
bool negate = false;
if(parser.NextToken().Type == TokenType::OpSub)
@@ -572,6 +586,11 @@ namespace renderer_test
entry.name = builder;
}
+ else if (parser.LookAhead("bindless"))
+ {
+ parser.ReadToken();
+ entry.isBindlessObject = true;
+ }
else
{
fprintf(stderr, "Invalid TEST_INPUT syntax '%s'\n", parser.NextToken().Content.getBuffer());
@@ -601,6 +620,8 @@ namespace renderer_test
for (Index entryIndex = 0; entryIndex < entries.getCount(); ++entryIndex)
{
auto& entry = entries[entryIndex];
+ if (entry.isBindlessObject)
+ continue;
if (entry.name.getLength() == 0)
{
diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h
index 4abbd6fb5..97796d7f6 100644
--- a/tools/render-test/shader-input-layout.h
+++ b/tools/render-test/shader-input-layout.h
@@ -75,19 +75,26 @@ struct RTTIDataEntry
unsigned int offset;
};
+struct BindlessHandleDataEntry
+{
+ unsigned int offset;
+ Slang::String name;
+};
+
class ShaderInputLayoutEntry
{
public:
ShaderInputType type;
Slang::List<unsigned int> bufferData;
Slang::List<RTTIDataEntry> rttiEntries;
+ Slang::List<BindlessHandleDataEntry> bindlessHandleEntry;
InputTextureDesc textureDesc;
InputBufferDesc bufferDesc;
InputSamplerDesc samplerDesc;
ArrayDesc arrayDesc;
bool isOutput = false;
bool onlyCPULikeBinding = false; ///< If true, only use on targets that have 'uniform' or 'CPU like' binding, like CPU and CUDA
-
+ bool isBindlessObject = false; ///< If true, this is a bindless object with no associated binding point in the shader.
Slang::String name; ///< Optional name. Useful for binding through reflection.
};