summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlucy96chen <47800040+lucy96chen@users.noreply.github.com>2022-10-12 14:41:22 -0700
committerGitHub <noreply@github.com>2022-10-12 14:41:22 -0700
commit53b180a9383668246a152af41aec8f6e565904a4 (patch)
treec034dc6584dd7dd7b5451d9fd8b3972e6b5d0106
parentf0cd62b37c5dfbbdb3fb205f1be2b8beba0dfed4 (diff)
Add specialization args test (#2444)
* Added specialization args test; small cleanup changes to slang-digest.h * Moved slang::Digest inside namespace Slang
-rw-r--r--source/core/slang-digest.h8
-rw-r--r--source/slang/slang-hash-utils.h11
-rw-r--r--source/slang/slang.cpp9
-rw-r--r--tools/gfx-unit-test/shader-cache-tests.cpp125
4 files changed, 135 insertions, 18 deletions
diff --git a/source/core/slang-digest.h b/source/core/slang-digest.h
index d1bc80b40..47c0cd8f7 100644
--- a/source/core/slang-digest.h
+++ b/source/core/slang-digest.h
@@ -4,6 +4,8 @@
namespace Slang
{
+ using slang::Digest;
+
// Wrapper struct that holds objects necessary for hashing.
struct DigestBuilder
{
@@ -19,9 +21,11 @@ namespace Slang
hashGen.update(&context, item);
}
- void finalize(slang::Digest* outHash)
+ Digest finalize()
{
- hashGen.finalize(&context, outHash);
+ Digest hash;
+ hashGen.finalize(&context, &hash);
+ return hash;
}
private:
diff --git a/source/slang/slang-hash-utils.h b/source/slang/slang-hash-utils.h
index d0d610cb8..62232dd21 100644
--- a/source/slang/slang-hash-utils.h
+++ b/source/slang/slang-hash-utils.h
@@ -12,11 +12,7 @@ namespace Slang
{
DigestBuilder builder;
builder.addToDigest(text);
-
- slang::Digest textHash;
- builder.finalize(&textHash);
-
- return textHash;
+ return builder.finalize();
}
// Combines the two provided hashes.
@@ -25,10 +21,7 @@ namespace Slang
DigestBuilder builder;
builder.addToDigest(hashA);
builder.addToDigest(hashB);
-
- slang::Digest combined;
- builder.finalize(&combined);
- return combined;
+ return builder.finalize();
}
// Returns the stored hash in checksum as a String.
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index a6dcf8ab2..20cad2465 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -3482,19 +3482,14 @@ SLANG_NO_THROW void SLANG_MCALL ComponentType::computeDependencyBasedHash(
auto entryPointNameOverride = getEntryPointNameOverride(entryPointIndex);
builder.addToDigest(entryPointNameOverride);
- slang::Digest hash;
- builder.finalize(&hash);
- *outHash = hash;
+ *outHash = builder.finalize();
}
SLANG_NO_THROW void SLANG_MCALL ComponentType::computeASTBasedHash(slang::Digest* outHash)
{
DigestBuilder builder;
updateASTBasedHash(builder);
-
- slang::Digest hash;
- builder.finalize(&hash);
- *outHash = hash;
+ *outHash = builder.finalize();
}
SLANG_NO_THROW SlangResult SLANG_MCALL ComponentType::getEntryPointHostCallable(
diff --git a/tools/gfx-unit-test/shader-cache-tests.cpp b/tools/gfx-unit-test/shader-cache-tests.cpp
index 184b71c06..67d7289aa 100644
--- a/tools/gfx-unit-test/shader-cache-tests.cpp
+++ b/tools/gfx-unit-test/shader-cache-tests.cpp
@@ -574,6 +574,121 @@ namespace gfx_test
}
};
+ // One shader featuring multiple kinds of shader objects that can be bound.
+ struct SpecializationArgsEntries : BaseShaderCacheTest
+ {
+ slang::ProgramLayout* slangReflection;
+
+ void createAddTransformer(IShaderObject** transformer)
+ {
+ slang::TypeReflection* addTransformerType =
+ slangReflection->findTypeByName("AddTransformer");
+ GFX_CHECK_CALL_ABORT(device->createShaderObject(
+ addTransformerType, ShaderObjectContainerType::None, transformer));
+
+ float c = 1.0f;
+ ShaderCursor(*transformer).getPath("c").setData(&c, sizeof(float));
+ }
+
+ void createMulTransformer(IShaderObject** transformer)
+ {
+ slang::TypeReflection* mulTransformerType =
+ slangReflection->findTypeByName("MulTransformer");
+ GFX_CHECK_CALL_ABORT(device->createShaderObject(
+ mulTransformerType, ShaderObjectContainerType::None, transformer));
+
+ float c = 1.0f;
+ ShaderCursor(*transformer).getPath("c").setData(&c, sizeof(float));
+ }
+
+ void submitGPUWork(GfxIndex transformerType)
+ {
+ Slang::ComPtr<ITransientResourceHeap> transientHeap;
+ ITransientResourceHeap::Desc transientHeapDesc = {};
+ transientHeapDesc.constantBufferSize = 4096;
+ GFX_CHECK_CALL_ABORT(
+ device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef()));
+
+ ICommandQueue::Desc queueDesc = { ICommandQueue::QueueType::Graphics };
+ auto queue = device->createCommandQueue(queueDesc);
+
+ auto commandBuffer = transientHeap->createCommandBuffer();
+ auto encoder = commandBuffer->encodeComputeCommands();
+
+ auto rootObject = encoder->bindPipeline(pipelineState);
+
+ ComPtr<IShaderObject> transformer;
+ switch (transformerType)
+ {
+ case 0:
+ createAddTransformer(transformer.writeRef());
+ break;
+ case 1:
+ createMulTransformer(transformer.writeRef());
+ break;
+ default:
+ /* Should not get here */
+ SLANG_IGNORE_TEST;
+ }
+
+ ShaderCursor entryPointCursor(rootObject->getEntryPoint(0));
+ entryPointCursor.getPath("buffer").setResource(bufferView);
+
+ entryPointCursor.getPath("transformer").setObject(transformer);
+
+ encoder->dispatchCompute(1, 1, 1);
+ encoder->endEncoding();
+ commandBuffer->close();
+ queue->executeCommandBuffer(commandBuffer);
+ queue->waitOnHost();
+ }
+
+ void generateNewPipelineState()
+ {
+ ComPtr<IShaderProgram> shaderProgram;
+
+ GFX_CHECK_CALL_ABORT(loadComputeProgram(device, shaderProgram, "compute-smoke", "computeMain", slangReflection));
+
+ ComputePipelineStateDesc pipelineDesc = {};
+ pipelineDesc.program = shaderProgram.get();
+ GFX_CHECK_CALL_ABORT(
+ device->createComputePipelineState(pipelineDesc, pipelineState.writeRef()));
+ }
+
+ void run()
+ {
+ ComPtr<IShaderCacheStatistics> shaderCacheStats;
+
+ // Due to needing a workaround to prevent loading old, outdated modules, we need to
+ // recreate the device between each segment of the test. However, we need to maintain the
+ // same cache filesystem for the duration of the test, so the device is immediately recreated
+ // to ensure we can pass the filesystem all the way through.
+ //
+ // TODO: Remove the repeated generateNewDevice() and createRequiredResources() calls once
+ // a solution exists that allows source code changes under the same module name to be picked
+ // up on load.
+ generateNewDevice();
+ createRequiredResources();
+ generateNewPipelineState();
+ submitGPUWork(0);
+
+ device->queryInterface(SLANG_UUID_IShaderCacheStatistics, (void**)shaderCacheStats.writeRef());
+ SLANG_CHECK(shaderCacheStats->getCacheMissCount() == 1);
+ SLANG_CHECK(shaderCacheStats->getCacheHitCount() == 0);
+ SLANG_CHECK(shaderCacheStats->getCacheEntryDirtyCount() == 0);
+
+ generateNewDevice();
+ createRequiredResources();
+ generateNewPipelineState();
+ submitGPUWork(1);
+
+ device->queryInterface(SLANG_UUID_IShaderCacheStatistics, (void**)shaderCacheStats.writeRef());
+ SLANG_CHECK(shaderCacheStats->getCacheMissCount() == 1);
+ SLANG_CHECK(shaderCacheStats->getCacheHitCount() == 0);
+ SLANG_CHECK(shaderCacheStats->getCacheEntryDirtyCount() == 0);
+ }
+ };
+
template <typename T>
void shaderCacheTestImpl(ComPtr<IDevice> device, UnitTestContext* context)
{
@@ -621,4 +736,14 @@ namespace gfx_test
{
runTestImpl(shaderCacheTestImpl<ShaderFileImportsShaderCache>, unitTestContext, Slang::RenderApiFlag::Vulkan);
}
+
+ SLANG_UNIT_TEST(specializationArgsShaderCacheD3D12)
+ {
+ runTestImpl(shaderCacheTestImpl<SpecializationArgsEntries>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ }
+
+ SLANG_UNIT_TEST(specializationArgsShaderCacheVulkan)
+ {
+ runTestImpl(shaderCacheTestImpl<SpecializationArgsEntries>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
}