diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2021-03-17 12:55:30 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-17 12:55:30 -0700 |
| commit | 6e5d85efb9fa5f647f7f0c7ef784a9fd09b29023 (patch) | |
| tree | 6206ef11502a1a5d9c1dc00df359be9aececffdf /tools/render-test/bind-location.h | |
| parent | b64a23cccfe9876d53cda773afc796bd975fa7e5 (diff) | |
Remove old code paths from render-test (#1760)
* Remove old code paths from render-test
Historically, the `render-test` tool was using three different code paths:
* One based on `gfx` and manual (non-reflection-based) parameter setting, used for OpenGL, D3D11, D3D12, and Vulkan
* One for CPU that used reflection-based parameter setting but shared no code with the first
* One for CUDA that used reflection-based parameter setting and shared some, but not all, code with the CPU path
Recently we've updated `render-test` to include a fourth option:
* Using `gfx` and the "shader object" system it exposes for a unified reflection-based parameter-setting system taht works across OpenGL, D3D11, D3D12, Vulkan, CUDA, and CPU
This change removes the first three options and leaves only the single unified path. A sa result, a bunch of code in `render-test` is no longer needed, and the codebase no longer relies on things like the `IDescriptorSet`-related APIs in `gfx`.
Several existing tests had to be disabled to make this change possible. Those tests will need to be audited and either re-enabled once we fix issues in the shader object system, or permanently removed if they don't test stuff we intend to support in the long run (e.g., global-scope type parameters, which aren't a clear necessity).
* fixup: CUDA detection logic
Diffstat (limited to 'tools/render-test/bind-location.h')
| -rw-r--r-- | tools/render-test/bind-location.h | 452 |
1 files changed, 0 insertions, 452 deletions
diff --git a/tools/render-test/bind-location.h b/tools/render-test/bind-location.h deleted file mode 100644 index 33670bf4b..000000000 --- a/tools/render-test/bind-location.h +++ /dev/null @@ -1,452 +0,0 @@ -#ifndef BIND_LOCATION_H -#define BIND_LOCATION_H - -#include "source/core/slang-basic.h" -#include "source/core/slang-free-list.h" -#include "source/core/slang-memory-arena.h" -#include "source/core/slang-writer.h" - -#include "slang.h" - -namespace renderer_test { - -/* -Bind Set/Point/Value -==================== - -The following classes are designed as a mechanism to simplify binding within the test system. The underlying issues are - -* How binding occurs is very dependent on the underlying target (CPU is different from Dx for example) - + CPU everything is just backed by uniform 'memory'/GPU uses different registers for different types - + With unbound arrays CPU can just indirect to a buffer, on GPU it might need use of register spaces or some other mechanism (as in VK) - + CPU groups together global/entry point parameters, GPU typically does not -* Having a mechanism that will the data/binding for the test independent of the actual target, allows that code/implementation to be shared across many targets. -* How a resource/state is configured within binding also varies significantly between targets - -One way to handle this disparity, would be to build an abstraction layer, that could create the device specific -resources/state and set them. This is not the approach taken here though. The idea here is to have a mechanism to -be able to build structures in memory, and record where binding takes place without having to create any -device specific resources or state. This data can then be used to construct and then bind as is appropriate. - -The process broadly for test system is is - -1) Set up any default buffers required for a target (for example the uniform/entry point buffers for CPU) -2) Add any default Value/buffers that are needed by traversing reflection -3) Create/Set the Values for the elements of ShaderInputLayoutEntry -4) Go through the values set on the BindSet, creating Resources/State etc appropriate for the target -5) Go through the bindings setting the Resource bindings as appropriate for the target -6) Execute -7) If the computation takes place outside of Values backing memory, copy back the data for output entries -8) Write the output entries - -To do this we need a mechanism to store a binding location. In the general case a BindingLocation might -track the location of many different categories of data. - -We also need a way to record what we want to create on the device for execution. To do this we have the -BindSet::Value. 'Value' was used instead of 'Resource' because the types of things the Value might represent -may not be resource like or might be multiple resources. In simple use cases though a 'Value' is typically -synonymous with some kind of Resource on the device. - -A Value knows the underlying type it represents as was determined via the slang layout/reflection. That an added -feature of 'Values' is there are able hold a buffer that is typically mapped onto some linear buffer on the -device. Doing so means that we do not need to store BindLocation mappings for say uniform data (like float or -matrix), it can just be stored in the memory buffer. When the resources are constructed for execution, we can -just copy over that data. - -This all sounds well and good but there is a final underlying important aspect. That is that some resource -like bindings may have to be stored in a buffer. For example on a CPU we could have a constant buffer that contained -another constant buffer as a field. On CPU this field would be converted into a pointer which needs to be set up. On CUDA this might be some -device specific value. So before we can copy the memory representation to a device specific buffer we must convert -any such bindings into something appropriate in the memory buffer associated with the Value. To do this we can traverse -a record of all of the bindings (which are held on the BindSet), and then set the appropriate date for the device from -data stored in the associated 'Value'. - -A final observation is that on CPU targets, the memory buffer held in the Value can just be used directly. - -NOTE: - -That these classes are written so they can be used to track locations across multiple categories such that binding -can work across many different types of targets. For the moment the mechanism/s are only tested on CPU like binding, -and there are quirks in how locations are traversed that have knowledge of how such bindings work. It may be necessary -for this to work more generally to only allow certain kinds of transitions based on some well defined specific -binding styles. -*/ - -/* A bind point records a specific binding point (typically for a category). It records a space and an offset. -As with Slangs layout reflection, the offset meaning is dependent on category. It might be an offset to -a 'register'. If category is 'uniform' it might be a memory offset. The space defines the 'space' a register -is in. -Note that m_space is ignored (but must be valid) for uniform offsets. -*/ -struct BindPoint -{ - typedef BindPoint ThisType; - - /// - bool isValid() const { return m_space >= 0; } - bool isInvalid() const { return m_space < 0; } - - void setInvalid() { m_space = -1; m_offset = 0; } - - bool operator==(const ThisType& rhs) const { return m_space == rhs.m_space && m_offset == rhs.m_offset; } - bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - - Slang::HashCode getHashCode() const { return Slang::combineHash(Slang::getHashCode(m_space), Slang::getHashCode(m_offset)); } - - BindPoint() = default; - BindPoint(Slang::Index space, size_t offset):m_space(space), m_offset(offset) {} - - static BindPoint makeInvalid() { return BindPoint(-1, 0); } - - Slang::Index m_space = 0; ///< The register space - size_t m_offset = 0; ///< The offset, might be a byte address or a register index -}; - -/* Stores the BindPoints by category. */ -struct BindPoints -{ - typedef BindPoints ThisType; - - Slang::Index findSingle() const - { - Slang::Index found; - if (calcValidCount(&found) == 1) - { - return found; - } - return -1; - } - Slang::Index calcValidCount(Slang::Index* outFoundIndex) const - { - using namespace Slang; - Index found = -1; - Index validCount = 0; - for (Index i = 0; i < Index(SLANG_PARAMETER_CATEGORY_COUNT); ++i) - { - const auto& point = m_points[i]; - if (point.isValid()) - { - found = i; - validCount++; - } - } - if (outFoundIndex) - { - *outFoundIndex = found; - } - return validCount; - } - void setInvalid() - { - for (auto& point : m_points) - { - point.setInvalid(); - } - } - - bool operator==(const ThisType& rhs) const - { - for (Slang::Index i = 0; i < SLANG_PARAMETER_CATEGORY_COUNT; ++i) - { - if (m_points[i] != rhs.m_points[i]) - { - return false; - } - } - return true; - } - bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - - Slang::HashCode getHashCode() const - { - using namespace Slang; - HashCode hash = 0x5435abbc; - int bits = 0; - int bit = 1; - for (Index i = 0; i < SLANG_PARAMETER_CATEGORY_COUNT; ++i, bit += bit) - { - const auto& point = m_points[i]; - if (point.isValid()) - { - hash = combineHash(hash, point.getHashCode()); - bits |= bit; - } - } - // The categories set is important too, so merge that in - return combineHash(bits, hash); - } - - BindPoint& operator[](SlangParameterCategory category) { return m_points[Slang::Index(category)]; } - const BindPoint& operator[](SlangParameterCategory category) const { return m_points[Slang::Index(category)]; } - - BindPoint m_points[SLANG_PARAMETER_CATEGORY_COUNT]; -}; - -/* A BindPointSet is really just a reference counted 'BindPoints'. This allows for BindPoints to be shared between -multiple BindLocations if they hold the same value. */ -class BindPointSet : public Slang::RefObject -{ -public: - typedef Slang::RefObject Super; - - Slang::HashCode getHashCode() const { return m_points.getHashCode(); } - - BindPointSet(const BindPoints& points) : - m_points(points) - { - } - BindPointSet() {} - - BindPoints m_points; -}; - -/* A BindSet::Value represents a 'value' associated with a binding. Typically it will be a Resource type -like a Buffer/Texture on a target device. As well as recording type information, it can also store a chunk -of memory that can hold uniform data, and may hold bindings for some kinds of targets (for example CPU pointers). -Additionally if the Value holds some kind of array, the amount of elements in the array can be stored in m_elementCount. - -All Value are constructed stored and tracked on a BindSet. When a BindSet is destroyed any associated Value will become -destroyed. -*/ -struct BindSet_Value -{ - slang::TypeReflection::Kind m_kind; ///< The kind, used if type is not set. Same as m_type.kind otherwise - slang::TypeLayoutReflection* m_type; ///< The type - uint8_t* m_data; - size_t m_sizeInBytes; ///< Total size in bytes - size_t m_elementCount; ///< Only applicable on an array like type, else 0 - - /// Can be set by user code to indicate the origin of contents/definition of a value, such that actual resource can be later constructed. - /// -1 is used to indicate it is not set. - Slang::Index m_userIndex = -1; - - Slang::RefPtr<Slang::RefObject> m_target; ///< Can be used to store data related to an actual target resource. -}; - -class BindSet; - -/* Specifies a binding location (including the associated slang reflection type information) - -It really can be in 3 type of state. -1) Invalid - not a valid binding (m_typeLayout is null, m_pointSet is not used. -2) Holds a single bind point defined by category and BindPoint m_point (m_category and m_point are used) -3) Hold multiple bind points by category (in this case m_bindPointSet is used) - -NOTE! it is an invariant - that the BindLocation must always be in the 'simplest' form that can represent it. -That is if there is only a single binding it *cannot* be stored as a m_bindPointSet with a single category - -That construction through BindPoints, will do this determination automatically. - -A BindLocation can be stored in a Hash. -*/ -struct BindLocation -{ - typedef BindLocation ThisType; - - bool isValid() const { return m_typeLayout != nullptr; } - bool isInvalid() const { return m_typeLayout == nullptr; } - - const BindPointSet* getPointSet() const { return m_bindPointSet; } - void setPoints(const BindPoints& points); - - /// Add an offset - void addOffset(SlangParameterCategory category, ptrdiff_t offset); - - /// True if holds tracking for this category - bool hasCategory(SlangParameterCategory category) const { return getBindPointForCategory(category).isValid(); } - - BindPoint getBindPointForCategory(SlangParameterCategory category) const; - BindPoint* getValidBindPointForCategory(SlangParameterCategory category); - const BindPoint* getValidBindPointForCategory(SlangParameterCategory category) const; - slang::TypeLayoutReflection* getTypeLayout() const { return m_typeLayout; } - - void setEmptyBinding() { m_bindPointSet.setNull(); m_point = BindPoint::makeInvalid(); m_category = SLANG_PARAMETER_CATEGORY_NONE; } - - template <typename T> - T* getUniform() const { return reinterpret_cast<T*>(getUniform(sizeof(T))); } - void* getUniform(size_t size) const; - - /// Set uniform data - SlangResult setUniform(const void* data, size_t sizeInBytes) const; - - bool operator==(const ThisType& rhs) const; - bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - - /// Get the hash code - Slang::HashCode getHashCode() const; - - /// Default Ctor - constructs as invalid - 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; - - /// An invalid location. - /// Better to return this than use default Ctor as indicates validity in code directly. - static const BindLocation Invalid; - - slang::TypeLayoutReflection* m_typeLayout = nullptr; ///< The type layout - - BindSet_Value* m_value = nullptr; ///< The value if we are in one. - - SlangParameterCategory m_category = SLANG_PARAMETER_CATEGORY_NONE; ///< If there isn't a set this defines the category - BindPoint m_point; ///< If there isn't a bind point set, this defines the point - - /// Holds multiple BindPoints. - /// To keep invariants (such that getHashCode and == work), it can only be set if - /// there is more than one category. If there is just one, m_category and m_point *MUST* be used. - /// NOTE! Can only be written to if there is a single reference. - Slang::RefPtr<BindPointSet> m_bindPointSet; -}; - -/* A BindSet holds all of the Value and bindings. It is designed to be used such that it can hold -all of the bind state needed for setting up a specific binding. - -Unfortunately it is not enough to lookup via a path for a Binding, because different targets represents the -'root' variables and values in different ways. The BindRoot interface is designed to handle this aspect. -*/ -class BindSet -{ -public: - typedef BindSet_Value Value; - - Value* getAt(const BindLocation& loc) const; - void setAt(const BindLocation& loc, Value* value); - void setAt(const BindLocation& loc, SlangParameterCategory category, Value* value); - - Value* createBufferValue(slang::TypeLayoutReflection* type, size_t sizeInBytes, const void* initialData = nullptr); - Value* createBufferValue(slang::TypeReflection::Kind kind, size_t sizeInBytes, const void* initialData = nullptr); - - Value* createTextureValue(slang::TypeLayoutReflection* type); - - /// Calculate from the current location everything that is referenced - void calcValueLocations(const BindLocation& location, Slang::List<BindLocation>& outLocations); - void calcChildResourceLocations(const BindLocation& location, Slang::List<BindLocation>& outLocations); - - void destroyValue(Value* value); - - BindLocation toField(const BindLocation& loc, slang::VariableLayoutReflection* field) const; - BindLocation toField(const BindLocation& loc, const char* name) const; - BindLocation toIndex(const BindLocation& location, Slang::Index index) const; - - SlangResult setBufferContents(const BindLocation& loc, const void* initialData, size_t sizeInBytes) const; - - /// Get all of the values - const Slang::List<Value*>& getValues() const { return m_values; } - /// Get all of the bindings - void getBindings(Slang::List<BindLocation>& outLocations, Slang::List<Value*>& outValues) const; - - /// - void releaseValueTargets(); - - /// Ctor - BindSet(); - - /// Dtor - ~BindSet(); - - /// True if is a texture type - static bool isTextureType(slang::TypeLayoutReflection* typeLayout); - -protected: - Value* _createBufferValue(slang::TypeReflection::Kind kind, slang::TypeLayoutReflection* typeLayout, size_t bufferSizeInBytes, size_t sizeInBytes, const void* initalData); - - Slang::List<Value*> m_values; - - Slang::Dictionary<BindLocation, Value*> m_bindings; - - Slang::MemoryArena m_arena; -}; - -/* BindRoot is an interface for finding the roots bindings by name. It is an interface because different targets have different ways of -representing how root values are located. -More specifically a CPU target holds the uniform and entry point variables in two buffers. -*/ -class BindRoot : public Slang::RefObject -{ -public: - typedef RefObject Super; - - typedef BindSet::Value Value; - - virtual BindLocation find(const char* name) = 0; - /// The setting of an array count is dependent on the underlying implementation. - /// On the CPU this means making sure there is a buffer that is large enough - /// And using that for storage. - /// But this does NOT set the actual location in the appropriate manner - that is - /// something that has to be done by the process that sets all the 'resource' handles etc elsewhere - virtual SlangResult setArrayCount(const BindLocation& location, int count) = 0; - - /// Find all of the roots - virtual void getRoots(Slang::List<BindLocation>& outLocations) = 0; - - /// Parse (specifying some location in HLSL style expression) slice to get to a location. - SlangResult parse(const Slang::String& text, const Slang::String& sourcePath, Slang::WriterHelper streamOut, BindLocation& outLocation); - - /// 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 -the entry point variables/uniforms in buffers. This type also stores the Value/Buffers for -the 'root', and entry point, so they can be directly accessed. -*/ -class CPULikeBindRoot : 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; - - void addDefaultValues(); - - Value* getRootValue() const { return m_rootValue; } - Value* getEntryPointValue() const { return m_entryPointValue; } - - void* getRootData() { return m_rootValue ? m_rootValue->m_data : nullptr; } - void* getEntryPointData() { return m_entryPointValue ? m_entryPointValue->m_data : nullptr; } - - SlangResult init(BindSet* bindSet, slang::ShaderReflection* reflection, int entryPointIndex); - -protected: - // Used when we have uniform buffers (as used on CPU/CUDA) - - Value* m_rootValue = nullptr; - Value* m_entryPointValue = nullptr; -}; - -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 |
