The High-Level Shader Language[1] or High-Level Shading Language[2] (HLSL) is a proprietary shading language developed by Microsoft for the Direct3D 9 API to augment the shader assembly language, and went on to become the required shading language for the unified shader model of Direct3D 10 and higher.
HLSL is analogous to the GLSL shading language used with the OpenGL standard. It is very similar to the Nvidia Cg shading language, as it was developed alongside it. Early versions of the two languages were considered identical, only marketed differently.[3] HLSL shaders can enable profound speed and detail increases as well as many special effects in both 2D and 3D computer graphics.[citation needed]
HLSL programs come in six forms: pixel shaders (fragment in GLSL), vertex shaders, geometry shaders, compute shaders, tessellation shaders (Hull and Domain shaders), and ray tracing shaders (Ray Generation Shaders, Intersection Shaders, Any Hit/Closest Hit/Miss Shaders). A vertex shader is executed for each vertex that is submitted by the application, and is primarily responsible for transforming the vertex from object space to view space, generating texture coordinates, and calculating lighting coefficients such as the vertex's normal, tangent, and bitangent vectors. When a group of vertices (normally 3, to form a triangle) come through the vertex shader, their output position is interpolated to form pixels within its area; this process is known as rasterization.
Optionally, an application using a Direct3D 10/11/12 interface and Direct3D 10/11/12 hardware may also specify a geometry shader. This shader takes as its input some vertices of a primitive (triangle/line/point) and uses this data to generate/degenerate (or tessellate) additional primitives or to change the type of primitives, which are each then sent to the rasterizer.
GPUs listed are the hardware that first supported the given specifications. Manufacturers generally support all lower shader models through drivers. Note that games may claim to require a certain DirectX version, but don't necessarily require a GPU conforming to the full specification of that version, as developers can use a higher DirectX API version to target lower-Direct3D-spec hardware; for instance DirectX 9 exposes features of DirectX7-level hardware that DirectX7 did not, targeting their fixed-function T&L pipeline.
The HLSL shader model is a versioning approach indicating which new features are added to the language. Each level allows an application or game to target a well-known set of functionality for development, and allows hardware and driver developers to target that same description for support.
The High Level Shading Language for DirectX implements a series of shader models. Using HLSL, you can create C-like programmable shaders for the Direct3D pipeline. Each shader model builds on the capabilities of the model before it, implementing more functionality with fewer restrictions.
Shader model 1 started with DirectX 8 and included assembly level and C-like instructions. This model has many limitations caused by early programmable shader hardware. Shader model 2 and 3 greatly expanded on the number of instructions, and constants shaders could use. They are much more powerful than shader model 1, but still carry some of the existing limitations of the first shader model.
Starting with Windows Vista, shader model 4 is a complete redesign. It allows unlimited instructions and constants (within hardware constraints of your machine), has templated objects to make texture sampling cleaner and more efficient, and has the fewest restrictions of any shader model. It does however require the Windows Driver Model which is only available on the Windows Vista (or later) operating system.
For earlier shader models, HLSL programming exposes only a single thread of execution. New wave-level operations are provided, starting with model 6.0, to explicitly take advantage of the parallelism of current GPUs - many threads can be executing in lockstep on the same core simultaneously. For example, the model 6.0 intrinsics enable the elimination of barrier constructs when the scope of synchronization is within the width of the SIMD processor, or some other set of threads that are known to be atomic relative to each other.
Most of the intrinsics appear in pixel shaders and compute shaders, though there are some exceptions (noted for each function). The functions have been added to the requirements for DirectX Feature Level 12.0, under API level 12.
The parameter and return value for these functions implies the type of the expression, the supported types are those from the following list that are also present in the target shader model for your app:
These intrinsics compute the specified operation across all active lanes in the wave and broadcast the final result to all active lanes. Therefore, the final output is guaranteed uniform across the wave.
These intrinsics perform swap operations on the values across a wave known to contain pixel shader quads as defined here. The indices of the pixels in the quad are defined in scan-line or reading order - where the coordinates within a quad are:
These routines work in either compute shaders or pixel shaders. In compute shaders they operate in quads defined as evenly divided groups of 4 within an SIMD wave. In pixel shaders they should be used on waves captured by WaveQuadLanes, otherwise results are undefined.
You can use #pragma directives to indicate that a shaderA program that runs on the GPU. More info
See in Glossary requires certain GPU features. At runtime, Unity uses this information to determine whether a shader program is compatible with the current hardware.
You can specify individual GPU features with the #pragma require directive, or specify a shader model with the #pragma target directive. A shader model is a shorthand for a group of GPU features; internally, it is the same as a #pragma require directive with the same list of features.
It is important to correctly describe the GPU features that your shader requires. If your shader uses features that are not included in the list of requirements, this can result in either compile time errors, or in devices failing to support shaders at runtime.
If the list of requirements (or the equivalent target value) does not already include these values, Unity displays a warning message when it compiles the shader, to indicate that it has added these requirements. To avoid seeing this warning message, explicitly add the requirements or use an appropriate target value in your code.
You can also use the #pragma require directive followed by a colon and a list of space-delimited shader keywords. This means that the requirement applies only to variants that are used when any of the given keywords are enabled.
You can also use the #pragma target directive followed by a list of space-delimited shader keywords. This means that the requirement applies only to variants that are used when any of the given keywords are enabled.
You'll need to check the GPU capabilities through D3DCAPS (check the DirectX SDK docs if you don't know it). More than just determining the shader model, you can check for specific capabilities supported.
If you are using D3D9, you can query for device capabilities reported by your card using the IDirect3D9::GetDeviceCaps method. This will give you a structure containing a lot of interesting information about what the hardware supports. Of interest to you concerning this problem will the fields in the resulting structure called VertexShaderVersion and PixelShaderVersion as well as possibly MaxVertexShader30InstructionSlots and MaxPixelShader30InstructionSlots. All four are described on the linked documentation page.
For D3D10 you should be guaranteed SM4. For D3D11 (which I'd recommend over 10, since it should be the case that you can use 11 if you can use 10) device capabilities are categorized into feature levels. If you're using the 10_0 feature level or greater, you should be guaranteed SM4. Below the 10_0 level you have some odd 10Level9 differences to take into account -- the upshot for you is that you have to use odd shader model designations like vs_4_0_level_9_1 in some (perhaps all, we're getting into territory I haven't explored much in practice) scenarios.
You'll note that I said "should be guaranteed" in a few places. This is because, as you alluded to, it's possible for cards to lie or for there to be driver bugs that effectively render particular hardware/driver combinations "non functional" (or at least broken in a fashion you'd want to work around). This is much rarer these days than it used to be, but in these cases you can't really trust the hardware or driver anyhow and will have to "do it yourself." One way to do this is to simply try to create something using SM3 and see if it fails... although this will not catch all bugs/failures.
What I have done to account for that kind of issue in the past is build up a locally-maintained "feature database" API that allows me to store information about particular card/driver failures and how to fall back to safe alternative code paths when that hardware/driver combination is present on the end-user's machine. Populating this database generally requires trial-and-error and a lot of different hardware configurations, so can be difficult for the lone developer to do, unfortunately.
I am writing a small utility that reports system capabilities. One is the highest shader model supported by the installed graphics card, and I am currently detecting this using Direct3D 9.0c's device capabilities and checking the VertexShaderVersion and PixelShaderVersion fields of the D3DCAPS9 structure.
The utility has to run on Windows 2000 and above, and work on systems where a graphics card and even DirectX are not installed. I am currently dynamically loading DX9, so on those systems the check gracefully fails (which is ok.) But I am seeking a similar solution: something that will still run on all systems, and work correctly (detect the SM version) on most systems.
93ddb68554