diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2020-01-31 16:01:03 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-31 16:01:03 -0800 |
| commit | 2c1fbf8330efc34b85e09ee9b101c6a55327778a (patch) | |
| tree | 79707def5dec6a753bafaffcb474c8a92fb5081b /slang.h | |
| parent | 2ee06a4f2f3c995717bf18ba287a20e81d6141bc (diff) | |
Some Slang API additions (#1195)
* Some Slang API additions
These are additions to the public Slang API that came up while I was trying to write an example to demonstrate GPU printing. The additions aren't strictly necessary for the example, but I found these to be missing services when writing the code the way I wanted to.
The main public changes are:
* There is a new distinct `IEntryPoint` interface which inherit from `IComponentType` (much like `IModule` before). For now this doesn't expose any new functions on top of `IComponentType`, but I expect it to do so eventually.
* It is now possible to get the `IModule` for a specific translation unit in a compile request with `spCompileRequest_getModule`. Even for a compile request that had only one translation unit this is *not* the same object as gets returned by `spCompileRequest_getProgram`. The latter should probably be called `*_getLinkedProgram` because it returns a composite component type that links the module with everything it `import`s.
* An `IModule` can look up entry points declared in the module. Eventually a module should support looking up most of the declarations in the module (e.g., types) by name, but entry points are an obvious case.
* A new `link()` operation is added to `IComponentType`. It is possible to have component types that have unsatisfied dependencies, such that trying to generate kernel code from them will fail. The `link()` operation tries to produce a new composite component type that combines a component with its dependencies, to enable code generation. The implementation of end-to-end compilation was using a function like this internally, but it hadn't been exposed to the API.
Notes on the implementation:
* The list of entry points declared in a given translation unit has moved from `TranslationUnitRequest` to the `Module` inside of it.
* `EntryPoint` now has to do a song and dance much like `Module` to both inherit from `ComponentType` and support the `IEntryPoint` interface.
* The `Session* m_session` member in `Linkage` (in terms of public API, this is the `slang::ISession` holding a pointer to the `slang::IGlobalSession`) has been changed to a `RefPtr`. Without this change an application can't just hold onto a `ComPtr<slang::ISession>`; they also need to retain the `IGlobalSession` or things will crash. The new behavior seems more correct, but I worry that it might introduce a leak.
* The `asInternal` operation for `IComponentType` had to be updated to not just perform a cast. A type like `Module` has two `IComponentType` sub-objects, and only one of these is at the same address as the `ComponentType` base.
* Similarly, the `Module::getInterface` logic was changed to fall back to `Super::getInterface` for all the cases other than `IID_IModule`, so that it would be guaranteed to return the `IComponentType` at the same address as `ComponentType` in response to a `queryInterface`.
* Fixes for memory retain cycles
As part of the earlier change, I made the `Linkage` type hold a `RefPtr` to the `Session`.
The motivation there is it lets a user hang onto just a `slang::ISession` without having to also retain the `slang::IGlobalSession` for no immediately apparent reason.
There are two problems that this surfaced, one pre-existing and one new.
The new problem was that `Session` already held a `RefPtr<Linkage> m_builtinLinkage` for the linkage that holds the stdlib code.
I solved that problem by splitting the parent pointer in `Linkage` into two pointers: a raw pointer that is used to actually locate the parent session, and a ref-counted one that can be used to *optionally* retain the parent session.
The builtin linkage is then set up to explicitly not retain its parent, thus breaking the cycle.
The second problem was a pre-existing one, where every `ComponentType` was holding a retained pointer to its parent `Linkage`, but in turn the `Linkage` was holding retained pointers to many `ComponentTypes` (and subclasses thereof).
For this case I used the more expedient fix of making the parent pointer into a raw pointer, and figuring that it is a reasonable rule to expect user to retain the `Linkage` (aka `slang::ISession`) that owns a component type if they want to be able to use the component type.
I might need/want to investigate a better fix for the latter issue, but for now this seems to clean up the issues I was seeing in the tests. Fingers crossed.
Diffstat (limited to 'slang.h')
| -rw-r--r-- | slang.h | 73 |
1 files changed, 68 insertions, 5 deletions
@@ -3179,9 +3179,38 @@ namespace slang SlangInt specializationArgCount, IComponentType** outSpecializedComponentType, ISlangBlob** outDiagnostics = nullptr) = 0; + + /** Link this component type against all of its unsatisifed dependencies. + + A component type may have unsatisfied dependencies. For example, a module + depends on any other modules it `import`s, and an entry point depends + on the module that defined it. + + A user can manually satisfy dependencies by creating a composite + component type, and when doing so they retain full control over + the relative ordering of shader parameters in the resulting layout. + + It is an error to try to generate/access compiled kernel code for + a component type with unresolved dependencies, so if dependencies + remain after whatever manual composition steps an application + cares to peform, the `link()` function can be used to automatically + compose in any remaining dependencies. The order of parameters + (and hence the global layout) that results will be deterministic, + but is not currently documented. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL link( + IComponentType** outLinkedComponentType, + ISlangBlob** outDiagnostics = nullptr) = 0; }; #define SLANG_UUID_IComponentType { 0x5bc42be8, 0x5c50, 0x4929, { 0x9e, 0x5e, 0xd1, 0x5e, 0x7c, 0x24, 0x1, 0x5f } }; + struct IEntryPoint : public IComponentType + { + public: + }; + + #define SLANG_UUID_IEntryPoint { 0x8f241361, 0xf5bd, 0x4ca0, { 0xa3, 0xac, 0x2, 0xf7, 0xfa, 0x24, 0x2, 0xb8 } } + /** A module is the granularity of shader code compilation and loading. In most cases a module corresponds to a single compile "translation unit." @@ -3198,9 +3227,9 @@ namespace slang struct IModule : public IComponentType { public: - /** Note: eventually operations for looking up types or entry - points by name should appear here. - */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL findEntryPointByName( + char const* name, + IEntryPoint** outEntryPoint) = 0; }; #define SLANG_UUID_IModule { 0xc720e64, 0x8722, 0x4d31, { 0x89, 0x90, 0x63, 0x8a, 0x98, 0xb1, 0xc2, 0x79 } } @@ -3240,16 +3269,50 @@ namespace slang } } -/** +/** Get the (linked) program for a compile request. + +The linked program will include all of the global-scope modules for the +translation units in the program, plus any modules that they `import` +(transitively), specialized to any global specialization arguments that +were provided via the API. */ SLANG_API SlangResult spCompileRequest_getProgram( SlangCompileRequest* request, slang::IComponentType** outProgram); +/** Get the (partially linked) component type for an entry point. + +The returned component type will include the entry point at the +given index, and will be specialized using any specialization arguments +that were provided for it via the API. + +The returned component will *not* include the modules representing +the global scope and its dependencies/specialization, so a client +program will typically want to compose this component type with +the one returned by `spCompileRequest_getProgram` to get a complete +and usable component type from which kernel code can be requested. +*/ SLANG_API SlangResult spCompileRequest_getEntryPoint( SlangCompileRequest* request, SlangInt entryPointIndex, - slang::IComponentType** outEntryPoint); + slang::IComponentType** outEntryPoint); + +/** Get the (un-linked) module for a translation unit. + +The returned module will not be linked against any dependencies, +nor against any entry points (even entry points declared inside +the module). Similarly, the module will not be specialized +to the arguments that might have been provided via the API. + +This function provides an atomic unit of loaded code that +is suitable for looking up types and entry points in the +given module, and for linking together to produce a composite +program that matches the needs of an application. +*/ +SLANG_API SlangResult spCompileRequest_getModule( + SlangCompileRequest* request, + SlangInt translationUnitIndex, + slang::IModule** outModule); #endif |
