summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/bugs/dxbc-double-problem.slang30
-rw-r--r--tests/bugs/dxbc-double-problem.slang.expected.txt8
-rw-r--r--tools/render-test/bind-location.cpp235
-rw-r--r--tools/render-test/bind-location.h30
-rw-r--r--tools/render-test/options.cpp4
-rw-r--r--tools/render-test/options.h2
-rw-r--r--tools/render-test/render-test-main.cpp74
-rw-r--r--tools/render-test/shader-input-layout.cpp178
-rw-r--r--tools/render-test/shader-input-layout.h8
9 files changed, 446 insertions, 123 deletions
diff --git a/tests/bugs/dxbc-double-problem.slang b/tests/bugs/dxbc-double-problem.slang
new file mode 100644
index 000000000..1cd3ab204
--- /dev/null
+++ b/tests/bugs/dxbc-double-problem.slang
@@ -0,0 +1,30 @@
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -output-using-type
+//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -output-using-type
+//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute -output-using-type
+//TEST(compute):COMPARE_COMPUTE_EX:-dx12 -compute -use-dxil -output-using-type
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-dx12 -compute -output-using-type
+
+// The problem this test shows is around handling of double with dxbc on D3D12. In that combination
+// this code does not write the correct value into the first element - it appears as 0, where
+// clearly w * pi_180 where w = 1 means the answer is not zero.
+//
+// To demonstrate the problem, renable the -dx12 -compute -output-using-type test. It will output 0 for the first item.
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], stride=4):out, name outputBuffer
+RWStructuredBuffer<double> outputBuffer;
+
+[numthreads(1, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ double w = double(dispatchThreadID.x + 1) * 38.63323592724938038L;
+
+ double pi = 3.14159274101257324L;
+
+ double pi_180 = pi/180;
+ double rad = w * pi_180;
+
+ outputBuffer[0] = rad;
+ outputBuffer[1] = pi;
+ outputBuffer[2] = pi_180;
+ outputBuffer[3] = w;
+} \ No newline at end of file
diff --git a/tests/bugs/dxbc-double-problem.slang.expected.txt b/tests/bugs/dxbc-double-problem.slang.expected.txt
new file mode 100644
index 000000000..2cffc0e7c
--- /dev/null
+++ b/tests/bugs/dxbc-double-problem.slang.expected.txt
@@ -0,0 +1,8 @@
+0.674277
+3.141593
+0.017453
+38.633236
+0.000000
+0.000000
+0.000000
+0.000000
diff --git a/tools/render-test/bind-location.cpp b/tools/render-test/bind-location.cpp
index 73b492938..da344dc03 100644
--- a/tools/render-test/bind-location.cpp
+++ b/tools/render-test/bind-location.cpp
@@ -562,40 +562,62 @@ void BindSet::releaseValueTargets()
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BindLocation !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
BindLocation::BindLocation(slang::TypeLayoutReflection* typeLayout, const BindPoints& points, BindSet_Value* value) :
- m_typeLayout(typeLayout)
+ m_typeLayout(typeLayout),
+ m_value(value)
{
- Slang::Index categoryIndex;
- auto categoryCount = points.calcValidCount(&categoryIndex);
+ setPoints(points);
+}
- if (categoryCount == 0)
+BindLocation::BindLocation(slang::TypeLayoutReflection* typeLayout, SlangParameterCategory category, const BindPoint& point, BindSet_Value* value) :
+ m_category(category),
+ m_point(point),
+ m_typeLayout(typeLayout),
+ m_value(value)
+{
+}
+
+BindLocation::BindLocation(slang::VariableLayoutReflection* varLayout, BindSet_Value* value)
+{
+ m_value = value;
+ m_typeLayout = varLayout->getTypeLayout();
+
+ const Index categoryCount = Index(varLayout->getCategoryCount());
+
+ if (categoryCount <= 0)
{
- // If no categories - mark as invalid
- m_typeLayout = nullptr;
- m_category = slang::ParameterCategory::None;
+ *this = BindLocation::Invalid;
+ return;
}
else if (categoryCount == 1)
{
- // If 1, we don't want m_bindPointSet
- m_category = SlangParameterCategory(categoryIndex);
- m_point = points.m_points[categoryIndex];
+ const auto category = varLayout->getCategoryByIndex(0);
+
+ const auto offset = varLayout->getOffset(category);
+ const auto space = varLayout->getBindingSpace(category);
+
+ m_category = category;
+ m_point = BindPoint(Index(space), size_t(offset));
}
else
{
- // We don't use these
- m_category = SLANG_PARAMETER_CATEGORY_NONE;
- m_point.setInvalid();
+ BindPoints points;
+ points.setInvalid();
- // Create a bindpoint set
- m_bindPointSet = new BindPointSet(points);
- }
-}
+ for (Index i = 0; i < categoryCount; ++i)
+ {
+ const auto category = varLayout->getCategoryByIndex((unsigned int)i);
-BindLocation::BindLocation(slang::TypeLayoutReflection* typeLayout, SlangParameterCategory category, const BindPoint& point, BindSet_Value* value) :
- m_category(category),
- m_point(point),
- m_typeLayout(typeLayout),
- m_value(value)
-{
+ const auto offset = varLayout->getOffset(category);
+ const auto space = varLayout->getBindingSpace(category);
+
+ BindPoint& point = points.m_points[category];
+
+ point.m_offset = size_t(offset);
+ point.m_space = Index(space);
+ }
+
+ setPoints(points);
+ }
}
BindPoint* BindLocation::getValidBindPointForCategory(SlangParameterCategory category)
@@ -828,16 +850,69 @@ SlangResult BindRoot::parse(const String& text, const String& sourcePath, Writer
return SLANG_OK;
}
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPULikeBindRoot !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+slang::VariableLayoutReflection* BindRoot::getParameterByName(const char* name)
+{
+ const int parameterCount = m_reflection->getParameterCount();
+ for (int i = 0; i < parameterCount; ++i)
+ {
+ auto parameter = m_reflection->getParameterByIndex(i);
+ const char* paramName = parameter->getName();
+ if (strcmp(name, paramName) == 0)
+ {
+ return parameter;
+ }
+ }
-SlangResult CPULikeBindRoot::init(BindSet* bindSet, slang::ShaderReflection* reflection, int entryPointIndex)
+ return nullptr;
+}
+
+slang::VariableLayoutReflection* BindRoot::getEntryPointParameterByName(const char* name)
+{
+ const int parameterCount = int(m_entryPoint->getParameterCount());
+ for (int i = 0; i < parameterCount; ++i)
+ {
+ auto parameter = m_entryPoint->getParameterByIndex(i);
+ // If has a semantic we will ignore
+ if (parameter->getSemanticName())
+ {
+ continue;
+ }
+ if (strcmp(parameter->getName(), name) == 0)
+ {
+ return parameter;
+ }
+ }
+ return nullptr;
+}
+
+SlangResult BindRoot::init(BindSet* bindSet, slang::ShaderReflection* reflection, int entryPointIndex)
{
m_bindSet = bindSet;
-
m_reflection = reflection;
+ m_entryPoint = nullptr;
+
+ {
+ auto entryPointCount = int(reflection->getEntryPointCount());
+ if (entryPointIndex < 0 || entryPointIndex >= entryPointCount)
+ {
+ SLANG_ASSERT(!"Entry point index out of range");
+ return SLANG_FAIL;
+ }
+ m_entryPoint = reflection->getEntryPointByIndex(entryPointIndex);
+ }
+
+ return SLANG_OK;
+}
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CPULikeBindRoot !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SlangResult CPULikeBindRoot::init(BindSet* bindSet, slang::ShaderReflection* reflection, int entryPointIndex)
+{
m_rootValue = nullptr;
m_entryPointValue = nullptr;
+ SLANG_RETURN_ON_FAIL(Super::init(bindSet, reflection, entryPointIndex));
+
{
size_t globalConstantBuffer = reflection->getGlobalConstantBufferSize();
@@ -866,14 +941,6 @@ SlangResult CPULikeBindRoot::init(BindSet* bindSet, slang::ShaderReflection* ref
}
{
- auto entryPointCount = int(reflection->getEntryPointCount());
- if (entryPointIndex < 0 || entryPointIndex >= entryPointCount)
- {
- SLANG_ASSERT(!"Entry point index out of range");
- return SLANG_FAIL;
- }
-
- m_entryPoint = reflection->getEntryPointByIndex(entryPointIndex);
size_t entryPointParamsSizeInBytes = 0;
const int parameterCount = int(m_entryPoint->getParameterCount());
@@ -905,40 +972,7 @@ SlangResult CPULikeBindRoot::init(BindSet* bindSet, slang::ShaderReflection* ref
return SLANG_OK;
}
-slang::VariableLayoutReflection* CPULikeBindRoot::getParameterByName(const char* name)
-{
- const int parameterCount = m_reflection->getParameterCount();
- for (int i = 0; i < parameterCount; ++i)
- {
- auto parameter = m_reflection->getParameterByIndex(i);
- const char* paramName = parameter->getName();
- if (strcmp(name, paramName) == 0)
- {
- return parameter;
- }
- }
-
- return nullptr;
-}
-slang::VariableLayoutReflection* CPULikeBindRoot::getEntryPointParameterByName(const char* name)
-{
- const int parameterCount = int(m_entryPoint->getParameterCount());
- for (int i = 0; i < parameterCount; ++i)
- {
- auto parameter = m_entryPoint->getParameterByIndex(i);
- // If has a semantic we will ignore
- if (parameter->getSemanticName())
- {
- continue;
- }
- if (strcmp(parameter->getName(), name) == 0)
- {
- return parameter;
- }
- }
- return nullptr;
-}
BindLocation CPULikeBindRoot::find(const char* name)
{
@@ -1133,4 +1167,71 @@ void CPULikeBindRoot::addDefaultValues()
}
}
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! GPULikeBindRoot !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+BindLocation GPULikeBindRoot::find(const char* name)
+{
+ slang::VariableLayoutReflection* varLayout = nullptr;
+
+ varLayout = getParameterByName(name);
+ if (!varLayout)
+ {
+ varLayout = getEntryPointParameterByName(name);
+ }
+
+ if (!varLayout)
+ {
+ return BindLocation::Invalid;
+ }
+
+ return BindLocation(varLayout, nullptr);
+}
+
+SlangResult GPULikeBindRoot::setArrayCount(const BindLocation& location, int count)
+{
+ // TODO(JS):
+ // Not 100% clear how to handle this. If the mechanism uses 'spaces' there is nothing to do.
+ // If the size is an aspect of the binding, then we need to set up the binding information correctly. Depending on underlying
+ // API. This could perhaps be handled with a base class for m_target which meant we could just call that and it would
+ // do the right thing.
+ //
+ // For now, lets not worry.
+ return SLANG_OK;
+}
+
+void GPULikeBindRoot::getRoots(Slang::List<BindLocation>& outLocations)
+{
+ {
+ const int parameterCount = int(m_entryPoint->getParameterCount());
+ for (int i = 0; i < parameterCount; ++i)
+ {
+ auto parameter = m_entryPoint->getParameterByIndex(i);
+ // If has a semantic we will ignore
+ if (parameter->getSemanticName())
+ {
+ continue;
+ }
+
+ auto offset = parameter->getOffset(SLANG_PARAMETER_CATEGORY_UNIFORM);
+
+ BindLocation location(parameter, nullptr);
+ SLANG_ASSERT(location.isValid());
+
+ outLocations.add(location);
+ }
+ }
+ {
+ const int parameterCount = m_reflection->getParameterCount();
+ for (int i = 0; i < parameterCount; ++i)
+ {
+ auto parameter = m_reflection->getParameterByIndex(i);
+
+ BindLocation location(parameter, nullptr);
+ SLANG_ASSERT(location.isValid());
+
+ outLocations.add(location);
+ }
+ }
+}
+
} // renderer_test
diff --git a/tools/render-test/bind-location.h b/tools/render-test/bind-location.h
index e4119a103..0e1e907b8 100644
--- a/tools/render-test/bind-location.h
+++ b/tools/render-test/bind-location.h
@@ -278,6 +278,7 @@ struct BindLocation
BindLocation() {}
BindLocation(slang::TypeLayoutReflection* typeLayout, const BindPoints& points, BindSet_Value* value = nullptr);
BindLocation(slang::TypeLayoutReflection* typeLayout, SlangParameterCategory category, const BindPoint& point, BindSet_Value* value = nullptr);
+ BindLocation(slang::VariableLayoutReflection* varLayout, BindSet_Value* value = nullptr);
BindLocation(const ThisType& rhs) = default;
@@ -386,9 +387,17 @@ public:
/// Get the bindset
BindSet* getBindSet() const { return m_bindSet; }
+ slang::VariableLayoutReflection* getParameterByName(const char* name);
+ slang::VariableLayoutReflection* getEntryPointParameterByName(const char* name);
+
+ SlangResult init(BindSet* bindSet, slang::ShaderReflection* reflection, int entryPointIndex);
+
+
protected:
BindSet* m_bindSet = nullptr;
+ slang::EntryPointReflection* m_entryPoint = nullptr;
+ slang::ShaderReflection* m_reflection = nullptr;
};
/* A CPULike implementation of the BindRoot. This can be used for any binding that holds
@@ -405,9 +414,6 @@ public:
virtual SlangResult setArrayCount(const BindLocation& location, int count) SLANG_OVERRIDE;
virtual void getRoots(Slang::List<BindLocation>& outLocations) SLANG_OVERRIDE;
- slang::VariableLayoutReflection* getParameterByName(const char* name);
- slang::VariableLayoutReflection* getEntryPointParameterByName(const char* name);
-
void addDefaultValues();
Value* getRootValue() const { return m_rootValue; }
@@ -420,12 +426,26 @@ public:
protected:
// Used when we have uniform buffers (as used on CPU/CUDA)
- slang::ShaderReflection* m_reflection = nullptr;
+
Value* m_rootValue = nullptr;
Value* m_entryPointValue = nullptr;
- slang::EntryPointReflection* m_entryPoint;
};
+class GPULikeBindRoot : public BindRoot
+{
+public:
+ typedef BindRoot Super;
+
+ // BindRoot
+ virtual BindLocation find(const char* name) SLANG_OVERRIDE;
+ virtual SlangResult setArrayCount(const BindLocation& location, int count) SLANG_OVERRIDE;
+ virtual void getRoots(Slang::List<BindLocation>& outLocations) SLANG_OVERRIDE;
+
+protected:
+};
+
+
+
} // renderer_test
#endif //BIND_LOCATION_H
diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp
index 4d5d83ce5..fb433048c 100644
--- a/tools/render-test/options.cpp
+++ b/tools/render-test/options.cpp
@@ -185,6 +185,10 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s
gOptions.adapter = *argCursor++;
}
+ else if (strcmp(arg, "-output-using-type") == 0)
+ {
+ gOptions.outputUsingType = true;
+ }
else if (strcmp(arg, "-compute-dispatch") == 0)
{
if (argCursor == argEnd)
diff --git a/tools/render-test/options.h b/tools/render-test/options.h
index 1048a29f4..a8b7d5884 100644
--- a/tools/render-test/options.h
+++ b/tools/render-test/options.h
@@ -57,6 +57,8 @@ struct Options
char const* slangArgs[kMaxSlangArgs];
int slangArgCount = 0;
+ bool outputUsingType = false;
+
bool useDXIL = false;
bool onlyStartup = false;
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp
index 16f2d78d1..c0d105a64 100644
--- a/tools/render-test/render-test-main.cpp
+++ b/tools/render-test/render-test-main.cpp
@@ -82,7 +82,7 @@ class RenderTestApp : public WindowListener
BindingStateImpl* getBindingState() const { return m_bindingState; }
- Result writeBindingOutput(const char* fileName);
+ Result writeBindingOutput(BindRoot* bindRoot, const char* fileName);
Result writeScreen(const char* filename);
@@ -104,6 +104,8 @@ class RenderTestApp : public WindowListener
RefPtr<PipelineState> m_pipelineState;
RefPtr<BindingStateImpl> m_bindingState;
+ ShaderCompilerUtil::OutputAndLayout m_compilationOutput;
+
ShaderInputLayout m_shaderInputLayout; ///< The binding layout
int m_numAddedConstantBuffers; ///< Constant buffers can be added to the binding directly. Will be added at the end.
@@ -210,10 +212,9 @@ SlangResult RenderTestApp::initialize(SlangSession* session, Renderer* renderer,
Result RenderTestApp::_initializeShaders(SlangSession* session, Renderer* renderer, Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input)
{
- ShaderCompilerUtil::OutputAndLayout output;
- SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, gOptions.sourcePath, gOptions.compileArgs, gOptions.shaderType, input, output));
- m_shaderInputLayout = output.layout;
- m_shaderProgram = renderer->createProgram(output.output.desc);
+ SLANG_RETURN_ON_FAIL(ShaderCompilerUtil::compileWithLayout(session, gOptions.sourcePath, gOptions.compileArgs, gOptions.shaderType, input, m_compilationOutput));
+ m_shaderInputLayout = m_compilationOutput.layout;
+ m_shaderProgram = renderer->createProgram(m_compilationOutput.output.desc);
return m_shaderProgram ? SLANG_OK : SLANG_FAIL;
}
@@ -255,7 +256,7 @@ void RenderTestApp::finalize()
{
}
-Result RenderTestApp::writeBindingOutput(const char* fileName)
+Result RenderTestApp::writeBindingOutput(BindRoot* bindRoot, const char* fileName)
{
// Submit the work
m_renderer->submitGpuWork();
@@ -267,6 +268,7 @@ Result RenderTestApp::writeBindingOutput(const char* fileName)
{
return SLANG_FAIL;
}
+ FileWriter writer(f, WriterFlags(0));
for(auto binding : m_bindingState->outputBindings)
{
@@ -274,34 +276,30 @@ Result RenderTestApp::writeBindingOutput(const char* fileName)
const auto& layoutBinding = m_shaderInputLayout.entries[i];
assert(layoutBinding.isOutput);
+
+ if (binding.resource && binding.resource->isBuffer())
{
- if (binding.resource && binding.resource->isBuffer())
- {
- BufferResource* bufferResource = static_cast<BufferResource*>(binding.resource.Ptr());
- const size_t bufferSize = bufferResource->getDesc().sizeInBytes;
-
- unsigned int* ptr = (unsigned int*)m_renderer->map(bufferResource, MapFlavor::HostRead);
- if (!ptr)
- {
- fclose(f);
- return SLANG_FAIL;
- }
+ BufferResource* bufferResource = static_cast<BufferResource*>(binding.resource.Ptr());
+ const size_t bufferSize = bufferResource->getDesc().sizeInBytes;
- const int size = int(bufferSize / sizeof(unsigned int));
- for (int i = 0; i < size; ++i)
- {
- fprintf(f, "%X\n", ptr[i]);
- }
- m_renderer->unmap(bufferResource);
- }
- else
+ unsigned int* ptr = (unsigned int*)m_renderer->map(bufferResource, MapFlavor::HostRead);
+ if (!ptr)
{
- printf("invalid output type at %d.\n", int(i));
+ return SLANG_FAIL;
}
+
+ const SlangResult res = ShaderInputLayout::writeBinding(bindRoot, m_shaderInputLayout.entries[i], ptr, bufferSize, &writer);
+
+ m_renderer->unmap(bufferResource);
+
+ SLANG_RETURN_ON_FAIL(res);
+ }
+ else
+ {
+ printf("invalid output type at %d.\n", int(i));
}
}
- fclose(f);
-
+
return SLANG_OK;
}
@@ -374,7 +372,16 @@ Result RenderTestApp::update(Window* window)
{
if (gOptions.shaderType == Options::ShaderProgramType::Compute || gOptions.shaderType == Options::ShaderProgramType::GraphicsCompute)
{
- SLANG_RETURN_ON_FAIL(writeBindingOutput(gOptions.outputPath));
+ auto request = m_compilationOutput.output.request;
+ auto slangReflection = (slang::ShaderReflection*) spGetReflection(request);
+
+ BindSet bindSet;
+ GPULikeBindRoot bindRoot;
+ bindRoot.init(&bindSet, slangReflection, 0);
+
+ BindRoot* outputBindRoot = gOptions.outputUsingType ? &bindRoot : nullptr;
+
+ SLANG_RETURN_ON_FAIL(writeBindingOutput(outputBindRoot, gOptions.outputPath));
}
else
{
@@ -582,8 +589,11 @@ SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSe
if (gOptions.outputPath)
{
+ BindRoot* outputBindRoot = gOptions.outputUsingType ? &context.m_bindRoot : nullptr;
+
+
// Dump everything out that was written
- SLANG_RETURN_ON_FAIL(ShaderInputLayout::writeBindings(compilationAndLayout.layout, context.m_buffers, gOptions.outputPath));
+ SLANG_RETURN_ON_FAIL(ShaderInputLayout::writeBindings(outputBindRoot, compilationAndLayout.layout, context.m_buffers, gOptions.outputPath));
// Check all execution styles produce the same result
SLANG_RETURN_ON_FAIL(CPUComputeUtil::checkStyleConsistency(sharedLibrary, gOptions.computeDispatchSize, compilationAndLayout));
@@ -613,8 +623,10 @@ SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSe
if (gOptions.outputPath)
{
+ BindRoot* outputBindRoot = gOptions.outputUsingType ? &context.m_bindRoot : nullptr;
+
// Dump everything out that was written
- SLANG_RETURN_ON_FAIL(ShaderInputLayout::writeBindings(compilationAndLayout.layout, context.m_buffers, gOptions.outputPath));
+ SLANG_RETURN_ON_FAIL(ShaderInputLayout::writeBindings(outputBindRoot, compilationAndLayout.layout, context.m_buffers, gOptions.outputPath));
}
return SLANG_OK;
diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp
index ee4f5fc2c..44021c08a 100644
--- a/tools/render-test/shader-input-layout.cpp
+++ b/tools/render-test/shader-input-layout.cpp
@@ -698,42 +698,182 @@ namespace renderer_test
}
}
-
- /* static */SlangResult ShaderInputLayout::writeBindings(const ShaderInputLayout& layout, const List<BindSet::Value*>& buffers, const String& fileName)
+ /* static */SlangResult ShaderInputLayout::writeBinding(BindRoot* bindRoot, const ShaderInputLayoutEntry& entry, const void* data, size_t sizeInBytes, WriterHelper writer)
{
- FILE * f = fopen(fileName.getBuffer(), "wb");
- if (!f)
+ typedef slang::TypeReflection::ScalarType ScalarType;
+
+ slang::TypeReflection::ScalarType scalarType = slang::TypeReflection::ScalarType::None;
+
+ slang::TypeLayoutReflection* typeLayout = nullptr;
+
+ if (bindRoot && entry.name.getLength())
{
- return SLANG_FAIL;
+ BindLocation location;
+ if (SLANG_SUCCEEDED(bindRoot->parse(entry.name, "", writer, location)))
+ {
+ // We should have the type of the item
+ typeLayout = location.m_typeLayout;
+ }
}
- const auto& entries = layout.entries;
+ slang::TypeLayoutReflection* elementTypeLayout = nullptr;
- for (int i = 0; i < entries.getCount(); ++i)
+ if (typeLayout)
{
- const auto& entry = entries[i];
- if (entry.isOutput)
+ switch (typeLayout->getKind())
{
- BindSet::Value* buffer = buffers[i];
+
+ //case slang::TypeReflection::Kind::Struct:
+ case slang::TypeReflection::Kind::Array:
+ case slang::TypeReflection::Kind::Matrix:
+ case slang::TypeReflection::Kind::Vector:
+ {
+ elementTypeLayout = typeLayout->getElementTypeLayout();
+ break;
+ }
+ case slang::TypeReflection::Kind::Scalar:
+ {
+ elementTypeLayout = typeLayout;
+ break;
+ }
+ case slang::TypeReflection::Kind::Resource:
+ {
+ elementTypeLayout = typeLayout->getElementTypeLayout();
+ break;
+ }
+ case slang::TypeReflection::Kind::TextureBuffer:
+ case slang::TypeReflection::Kind::ShaderStorageBuffer:
+ {
+ elementTypeLayout = typeLayout->getElementTypeLayout();
+ break;
+ }
+ }
+ }
- unsigned int* ptr = (unsigned int*)buffer->m_data;
+ if (elementTypeLayout)
+ {
+ scalarType = elementTypeLayout->getScalarType();
+ }
- const int size = int(entry.bufferData.getCount());
- // Must be the same size or less than allocated buffer
- SLANG_ASSERT(size * sizeof(unsigned int) <= buffer->m_sizeInBytes);
- for (int i = 0; i < size; ++i)
+ switch (scalarType)
+ {
+ // TODO(JS):
+ // Bool is here, because it's not clear across APIs how bool is laid out in memory
+ // Float16 is here as we don't have a convert Float16 to float function laying around
+ default:
+ case ScalarType::None:
+ case ScalarType::Void:
+ case ScalarType::Bool:
+ case ScalarType::Float16:
+ {
+ auto ptr = (const uint32_t*)data;
+ const size_t size = sizeInBytes / sizeof(ptr[0]);
+ for (size_t i = 0; i < size; ++i)
{
- unsigned int v = ptr[i];
-
- fprintf(f, "%X\n", v);
+ uint32_t v = ptr[i];
+ writer.print("%X\n", v);
+ }
+ break;
+ }
+ case ScalarType::UInt32:
+ {
+ auto ptr = (const uint32_t*)data;
+ const size_t size = sizeInBytes / sizeof(ptr[0]);
+ for (size_t i = 0; i < size; ++i)
+ {
+ uint32_t v = ptr[i];
+ writer.print("%u\n", v);
+ }
+ break;
+ }
+ case ScalarType::Int32:
+ {
+ auto ptr = (const int32_t*)data;
+ const size_t size = sizeInBytes / sizeof(ptr[0]);
+ for (size_t i = 0; i < size; ++i)
+ {
+ int32_t v = ptr[i];
+ writer.print("%i\n", v);
+ }
+ break;
+ }
+ case ScalarType::Int64:
+ {
+ auto ptr = (const int64_t*)data;
+ const size_t size = sizeInBytes / sizeof(ptr[0]);
+ for (size_t i = 0; i < size; ++i)
+ {
+ int64_t v = ptr[i];
+ writer.print("%" PRId64 "\n", v);
+ }
+ break;
+ }
+ case ScalarType::UInt64:
+ {
+ auto ptr = (const uint64_t*)data;
+ const size_t size = sizeInBytes / sizeof(ptr[0]);
+ for (size_t i = 0; i < size; ++i)
+ {
+ uint64_t v = ptr[i];
+ writer.print("%" PRIu64 "\n", v);
+ }
+ break;
+ }
+ case ScalarType::Float32:
+ {
+ auto ptr = (const float*)data;
+ const size_t size = sizeInBytes / sizeof(ptr[0]);
+ for (size_t i = 0; i < size; ++i)
+ {
+ const float v = ptr[i];
+ writer.print("%f\n", v);
}
+ break;
+ }
+ case ScalarType::Float64:
+ {
+ auto ptr = (const double*)data;
+ const size_t size = sizeInBytes / sizeof(ptr[0]);
+ for (size_t i = 0; i < size; ++i)
+ {
+ const double v = ptr[i];
+ writer.print("%f\n", v);
+ }
+ break;
}
}
- fclose(f);
+
return SLANG_OK;
}
+ /* static */SlangResult ShaderInputLayout::writeBindings(BindRoot* bindRoot, const ShaderInputLayout& layout, const List<BindSet::Value*>& buffers, WriterHelper writer)
+ {
+ const auto& entries = layout.entries;
+ for (int i = 0; i < entries.getCount(); ++i)
+ {
+ const auto& entry = entries[i];
+ if (entry.isOutput)
+ {
+ BindSet::Value* buffer = buffers[i];
+ writeBinding(bindRoot, entries[i], buffer->m_data, buffer->m_sizeInBytes, writer);
+ }
+ }
+
+ return SLANG_OK;
+ }
+
+ /* static */SlangResult ShaderInputLayout::writeBindings(BindRoot* bindRoot, const ShaderInputLayout& layout, const List<BindSet::Value*>& buffers, const String& fileName)
+ {
+ FILE * f = fopen(fileName.getBuffer(), "wb");
+ if (!f)
+ {
+ return SLANG_FAIL;
+ }
+ FileWriter fileWriter(f, WriterFlags(0));
+ return writeBindings(bindRoot, layout, buffers, &fileWriter);
+ }
+
void generateTextureData(TextureData& output, const InputTextureDesc& desc)
{
switch (desc.format)
diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h
index 3399df848..5b0527e0f 100644
--- a/tools/render-test/shader-input-layout.h
+++ b/tools/render-test/shader-input-layout.h
@@ -106,8 +106,14 @@ public:
/// Put into outBuffer the value buffers that were set via addbindSetValues (which will set m_userIndex to be the entries index)
static void getValueBuffers(const Slang::List<ShaderInputLayoutEntry>& entries, const BindSet& bindSet, Slang::List<BindSet::Value*>& outBuffers);
+ /// Writes a binding, if bindRoot is set, will try to honor the underlying type when outputting. If not will dump as uint32_t hex.
+ static SlangResult writeBinding(BindRoot* bindRoot, const ShaderInputLayoutEntry& entry, const void* data, size_t sizeInBytes, Slang::WriterHelper writer);
+
+ /// Write all bindings, using data from buffers
+ static SlangResult writeBindings(BindRoot* bindRoot, const ShaderInputLayout& layout, const List<BindSet::Value*>& buffers, Slang::WriterHelper writer);
+
/// Write bindings from values in memory from buffers
- static SlangResult writeBindings(const ShaderInputLayout& layout, const Slang::List<BindSet::Value*>& buffers, const Slang::String& fileName);
+ static SlangResult writeBindings(BindRoot* bindRoot, const ShaderInputLayout& layout, const Slang::List<BindSet::Value*>& buffers, const Slang::String& fileName);
};
void generateTextureDataRGB8(TextureData& output, const InputTextureDesc& desc);