Overview of the texture view design in C++ AMP
In order to enhance C++ AMP texture support with more features such as sampling and mipmap levels, we redesigned the C++ AMP texture view APIs in Visual Studio 2013. In this blog post, I will give you an overview of the changes we made in the design of texture views compared to Visual Studio 2012 and the rationale behind our design. Hopefully it will help to enable you to pick the appropriate texture types for your needs.
Texture APIs in Visual Studio 2012
Due to the current hardware limitation, reading and writing the same texture resource in the same kernel is only supported for very limited cases: 1-component texture type with 32-bit non-norm formats. For all other cases, either read access or write access, but not both, can be performed on the same texture within the same kernel.
In C++ AMP of Visual Studio 2012, the main texture usages we focused on, were to take advantage of texture’s hardware caches optimized for spatial locality and to support sub-word packing. We wanted to enable C++ AMP users to use the texture type just like the array type, which has the ability to be read from and written to within the same kernel. Therefore, we decided to let the texture<T,N> type serve the 1 component read/write scenario, and other read-only usages and introduced a new type writeonly_texture_view<T,N> to handle write-only usages.
The following table summarizes the texture API design of C++ AMP in Visual Studio 2012:
type |
#Components |
Lambda capture |
Read |
Write |
texture<T, N> |
1 |
ref |
Yes |
Yes |
1 |
const ref |
Yes |
No |
|
2, 4 |
ref, const ref |
Yes |
No |
|
writeonly_texture_view<T, N> |
1, 2, 4 |
value |
No |
Yes |
Texture APIs in Visual Studio 2013
In Visual Studio 2013, we wanted to expose more hardware accelerated operations available for textures, such as sampling and mipmap level support. However, we encountered some design issues when trying to enhance the existing texture APIs with these new functionalities:
- Texture sampling and reading a range of mipmap levels are only supported on texture sources that are guaranteed to be read-only. However, with the existing texture APIs, we cannot determine at the compile time if a one component texture object is read-only or not. Note that a const reference to a texture object cannot guarantee that it’s a read-only texture resource since it’s possible to capture a non-const reference to a texture object and then convert it to a const reference which is very common in C++ due to const reference function parameters.
- The underlying platform supports binding a sub-range of mipmap levels of a texture for read, which is more efficient than binding the whole texture object. Neither the texture type nor the writeonly_texture_view type could represent such a read-only sub-range concept.
- In order to write into a texture with multiple mipmap levels, a writable texture resource must be bound to the specific mipmap level that is being written to. The texture type represents the whole texture object including all mipmap levels, thus, is not suitable to represent a specific mipmap level. The writeonly_texture_view type, on the other hand, cannot represent the case that a writable texture resource is bound to a specific mipmap level of a texture whose value type supports both read and write in the same kernel.
To address these issues, in Visual Studio 2013, we introduced two new texture view types: texture_view<const T, N> and texture_view<T, N> to represent read-only texture views and read/write texture views respectively, which are consistent to the array_view’s design. In order to be backward compatible, we kept texture and writeonly_texture_view APIs as they are in Visual Studio 2012, but we are deprecating writeonly_texture_view since its functionality is now a subset of texture_view<T, N>.
The following table summarizes the new C++ AMP texture API design in Visual Studio 2013:
type | #Comp | Lambda capture | Read | Write | sampling | MipLevel access |
texture<T, N> | 1 | ref | Yes | Yes | No (1) | level 0 |
| 1 | const ref | Yes | No (3) | No (1) | level 0 |
| 2, 4 | ref, const ref | Yes | No (2) | No (1) | level 0 |
writeonly_texture_view<T, N> (deprecated) | 1, 2, 4 | value | No (1) | Yes | No (1) | level 0 |
texture_view<const T, N> | 1,2,4 | value | Yes | No (1) | Yes | The range is defined upon construction; each level is dynamically indexable |
texture_view<T, N>
| 1 | value | Yes | Yes | No (1) | a specific level defined upon construction |
2, 4 | value | No (2) | Yes | No (1) | a specific level defined upon construction |
The number in the parenthesis after “No” indicates how the specific operation is disallowed:
1 -- No member function is defined for the operation;
2 -- Static assertion is triggered for cases that are statically known unsupported for the operation;
3 -- The member function for the operation is non-const, and thus not accessible by the const reference assuming the constness is not casted away; the results would be undefined if constness is casted away;
Note that currently texture_view does not have the automatic data management and movement functionality as array_view provides. A texture_view can only be accessed on the accelerator_view where the underlying texture resides. But this functionality may be added in the future release.
This concludes the overview of the C++ AMP texture view design in Visual Studio 2013. We will have separate blog posts diving into details of texture sampling and mipmap support. So stay tuned. As usual, we’d love to hear your feedbacks, comments and questions below or on our MSDN Forum.