diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp
index a984cee00..f704723db 100644
--- a/src/d3d9/d3d9_device.cpp
+++ b/src/d3d9/d3d9_device.cpp
@@ -3387,7 +3387,7 @@ namespace dxvk {
       BindShader<DxsoProgramTypes::VertexShader>(GetCommonShader(shader));
       m_vsShaderMasks = newShader->GetShaderMask();
 
-      UpdateTextureTypeMismatchesForShader(newShader, m_vsShaderMasks.samplerMask, caps::MaxTexturesPS + 1);
+      UpdateTextureTypeMismatchesForShader(newShader, m_vsShaderMasks.samplerMask, FirstVSSamplerSlot);
     }
     else {
       m_vsShaderMasks = D3D9ShaderMasks();
@@ -6415,10 +6415,10 @@ namespace dxvk {
   void D3D9DeviceEx::UpdateTextureTypeMismatchesForTexture(uint32_t stateSampler) {
     uint32_t shaderTextureIndex;
     const D3D9CommonShader* shader;
-    if (likely(stateSampler <= caps::MaxTexturesPS)) {
+    if (likely(IsPSSampler(stateSampler))) {
       shader = GetCommonShader(m_state.pixelShader);
       shaderTextureIndex = stateSampler;
-    } else if (unlikely(stateSampler >= caps::MaxTexturesPS + 1)) {
+    } else if (unlikely(IsVSSampler(stateSampler))) {
       shader = GetCommonShader(m_state.vertexShader);
       shaderTextureIndex = stateSampler - caps::MaxTexturesPS - 1;
     } else {
diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h
index cec35f3d4..3a2a4184d 100644
--- a/src/d3d9/d3d9_device.h
+++ b/src/d3d9/d3d9_device.h
@@ -653,15 +653,41 @@ namespace dxvk {
       const D3DDISPLAYMODEEX*      pFullscreenDisplayMode,
             IDirect3DSwapChain9**  ppSwapChain);
 
+    /**
+     * @brief Sets the given sampler state
+     *
+     * @param StateSampler Sampler index (according to our internal way of storing samplers)
+     * @param Type Sampler state type to change
+     * @param Value State value
+     */
     HRESULT SetStateSamplerState(
         DWORD               StateSampler,
         D3DSAMPLERSTATETYPE Type,
         DWORD               Value);
 
+    /**
+     * @brief Sets the given sampler texture
+     *
+     * @param StateSampler Sampler index (according to our internal way of storing samplers)
+     * @param pTexture Texture to use
+     */
     HRESULT SetStateTexture(DWORD StateSampler, IDirect3DBaseTexture9* pTexture);
 
+    /**
+     * @brief Sets the transform for the given sampler
+     *
+     * @param idx Sampler index (according to our internal way of storing samplers)
+     * @param pMatrix Transform matrix
+     */
     HRESULT SetStateTransform(uint32_t idx, const D3DMATRIX* pMatrix);
 
+    /**
+     * @brief Sets the fixed function texture processing state
+     *
+     * @param Stage Sampler index (according to our internal way of storing samplers)
+     * @param Type Fixed function texture stage type
+     * @param Value Value for the state
+     */
     HRESULT SetStateTextureStageState(
             DWORD                      Stage,
             D3D9TextureStageStateTypes Type,
@@ -818,8 +844,40 @@ namespace dxvk {
 
     void UpdateActiveFetch4(uint32_t stateSampler);
 
+    /**
+     * @brief Sets the mismatching texture type bits for all samplers if necessary.
+     *
+     * This function will check all samplers the shader uses and set the  set the mismatching texture type bit for the given sampler if it does not
+     * match the texture type expected by the respective shader.
+     *
+     * It will *not* unset the bit if the texture type does match.
+     *
+     * @param stateSampler Sampler index (according to our internal way of storing samplers)
+     */
+
+     /**
+      * @brief Sets the mismatching texture type bits for all samplers if necessary.
+      *
+      * This function will check all samplers the shader uses and set the  set the mismatching texture type bit for the given sampler if it does not
+      * match the texture type expected by the shader.
+      *
+      * @param shader The shader
+      * @param shaderSamplerMask Mask of all samplers that the shader uses (according to our internal way of storing samplers)
+      * @param shaderSamplerOffset First index of the shader's samplers according to our internal way of storing samplers.
+      *                            Used to transform the sampler indices that are relative to the entire pipeline to ones relative to the shader.
+      */
     void UpdateTextureTypeMismatchesForShader(const D3D9CommonShader* shader, uint32_t shaderSamplerMask, uint32_t shaderSamplerOffset);
 
+    /**
+     * @brief Sets the mismatching texture type bit for the given sampler.
+     *
+     * This function will set the mismatching texture type bit for the given sampler if it does not
+     * match the texture type expected by the respective shader.
+     *
+     * It will *not* unset the bit if the texture type does match.
+     *
+     * @param stateSampler Sampler index (according to our internal way of storing samplers)
+     */
     void UpdateTextureTypeMismatchesForTexture(uint32_t stateSampler);
 
     void UploadManagedTexture(D3D9CommonTexture* pResource);
diff --git a/src/d3d9/d3d9_shader.cpp b/src/d3d9/d3d9_shader.cpp
index 6ab5df3d7..f8807e0cb 100644
--- a/src/d3d9/d3d9_shader.cpp
+++ b/src/d3d9/d3d9_shader.cpp
@@ -63,7 +63,7 @@ namespace dxvk {
     // do an or per-draw in the device.
     // We shift by 17 because 16 ps samplers + 1 dmap (tess)
     if (ShaderStage == VK_SHADER_STAGE_VERTEX_BIT)
-      m_usedSamplers <<= caps::MaxTexturesPS + 1;
+      m_usedSamplers <<= FirstVSSamplerSlot;
 
     m_usedRTs      = pModule->usedRTs();
 
diff --git a/src/d3d9/d3d9_stateblock.cpp b/src/d3d9/d3d9_stateblock.cpp
index 8b62c1d58..ef8f76bb6 100644
--- a/src/d3d9/d3d9_stateblock.cpp
+++ b/src/d3d9/d3d9_stateblock.cpp
@@ -436,7 +436,7 @@ namespace dxvk {
   void D3D9StateBlock::CapturePixelSamplerStates() {
     m_captures.flags.set(D3D9CapturedStateFlag::SamplerStates);
 
-    for (uint32_t i = 0; i < caps::MaxTexturesPS + 1; i++) {
+    for (uint32_t i = 0; i < FirstVSSamplerSlot; i++) {
       m_captures.samplers.set(i, true);
 
       m_captures.samplerStates[i].set(D3DSAMP_ADDRESSU, true);
@@ -519,7 +519,7 @@ namespace dxvk {
   void D3D9StateBlock::CaptureVertexSamplerStates() {
     m_captures.flags.set(D3D9CapturedStateFlag::SamplerStates);
 
-    for (uint32_t i = caps::MaxTexturesPS + 1; i < SamplerCount; i++) {
+    for (uint32_t i = FirstVSSamplerSlot; i < SamplerCount; i++) {
       m_captures.samplers.set(i, true);
       m_captures.samplerStates[i].set(D3DSAMP_DMAPOFFSET, true);
     }
diff --git a/src/d3d9/d3d9_util.h b/src/d3d9/d3d9_util.h
index 76cd31a7c..4e9202282 100644
--- a/src/d3d9/d3d9_util.h
+++ b/src/d3d9/d3d9_util.h
@@ -44,6 +44,11 @@ namespace dxvk {
     }
   }
 
+  /**
+   * @brief Returns whether or not the sampler index is valid
+   *
+   * @param Sampler Sampler index (according to the API)
+   */
   inline bool InvalidSampler(DWORD Sampler) {
     if (Sampler >= caps::MaxTexturesPS && Sampler < D3DDMAPSAMPLER)
       return true;
@@ -54,6 +59,19 @@ namespace dxvk {
     return false;
   }
 
+  /**
+   * @brief The first sampler that belongs to the vertex shader according to our internal way of storing samplers
+   */
+  constexpr uint32_t FirstVSSamplerSlot = caps::MaxTexturesPS + 1;
+
+  /**
+   * @brief Remaps a sampler index by the API to an internal one
+   *
+   * Remaps the sampler index according to the way the API counts them to how we count and store them internally.
+   *
+   * @param Sampler Sampler index (according to API)
+   * @return DWORD Sampler index (according to our internal way of storing samplers)
+   */
   inline DWORD RemapSamplerState(DWORD Sampler) {
     if (Sampler >= D3DDMAPSAMPLER)
       Sampler = caps::MaxTexturesPS + (Sampler - D3DDMAPSAMPLER);
@@ -61,13 +79,62 @@ namespace dxvk {
     return Sampler;
   }
 
+  /**
+   * @brief Remaps the sampler from an index applying to the entire pipeline to one relative to the shader stage and returns the shader type
+   *
+   * The displacement map sampler will be treated as a 17th pixel shader sampler.
+   *
+   * @param Sampler Sampler index (according to our internal way of storing samplers)
+   * @return std::pair<DxsoProgramType, DWORD> Shader stage that it belongs to and the relative sampler index
+   */
   inline std::pair<DxsoProgramType, DWORD> RemapStateSamplerShader(DWORD Sampler) {
-    if (Sampler >= caps::MaxTexturesPS + 1)
-      return std::make_pair(DxsoProgramTypes::VertexShader, Sampler - caps::MaxTexturesPS - 1);
+    if (Sampler >= FirstVSSamplerSlot)
+      return std::make_pair(DxsoProgramTypes::VertexShader, Sampler - FirstVSSamplerSlot);
 
     return std::make_pair(DxsoProgramTypes::PixelShader, Sampler);
   }
 
+  /**
+   * @brief Returns whether the sampler belongs to the vertex shader.
+   *
+   * The displacement map sampler is part of a fixed function feature,
+   * so it does not belong to the vertex shader.
+   * Use IsDMAPSampler to check for that.
+   *
+   * @param Sampler Sampler index (according to our internal way of storing samplers)
+   */
+  inline bool IsVSSampler(uint32_t Sampler) {
+    return Sampler >= FirstVSSamplerSlot;
+  }
+
+  /**
+   * @brief Returns whether the sampler belongs to the pixel shader.
+   *
+   * The displacement map sampler is part of a fixed function feature,
+   * so (unlike in RemapStateSamplerShader) it does not belong to the pixel shader.
+   * Use IsDMAPSampler to check for that.
+   *
+   * @param Sampler Sampler index (according to our internal way of storing samplers)
+   */
+  inline bool IsPSSampler(uint32_t Sampler) {
+    return Sampler <= caps::MaxTexturesPS;
+  }
+
+  /**
+   * @brief Returns whether the sampler is the displacement map sampler
+   *
+   * @param Sampler Sampler index (according to our internal way of storing samplers)
+   */
+  inline bool IsDMAPSampler(uint32_t Sampler) {
+    return Sampler > caps::MaxTexturesPS;
+  }
+
+  /**
+   * @brief Remaps the sampler from an index (counted according to the API) to one relative to the shader stage and returns the shader type
+   *
+   * @param Sampler Sampler index (according to the API)
+   * @return std::pair<DxsoProgramType, DWORD> Shader stage that it belongs to and the relative sampler index
+   */
   inline std::pair<DxsoProgramType, DWORD> RemapSamplerShader(DWORD Sampler) {
     Sampler = RemapSamplerState(Sampler);
 
@@ -243,6 +310,9 @@ namespace dxvk {
            uint32_t(offsets[1].y) > extent.height;
   }
 
+  /**
+   * @brief Mirrors D3DTEXTURESTAGESTATETYPE but starts at 0
+   */
   enum D3D9TextureStageStateTypes : uint32_t
   {
       DXVK_TSS_COLOROP        =  0,
@@ -272,6 +342,12 @@ namespace dxvk {
   constexpr uint32_t DXVK_TSS_TCI_CAMERASPACEREFLECTIONVECTOR   = 0x00030000;
   constexpr uint32_t DXVK_TSS_TCI_SPHEREMAP                     = 0x00040000;
 
+  /**
+   * @brief Remaps a texture stage type by the API to an internal one
+   *
+   * @param Type Texture stage type according to the API
+   * @return D3D9TextureStageStateTypes Texture stage type according to our internal way of storing them
+   */
   inline D3D9TextureStageStateTypes RemapTextureStageStateType(D3DTEXTURESTAGESTATETYPE Type) {
     return D3D9TextureStageStateTypes(Type - 1);
   }
diff --git a/src/dxso/dxso_compiler.cpp b/src/dxso/dxso_compiler.cpp
index 54c0f0543..1d7e1bf1d 100644
--- a/src/dxso/dxso_compiler.cpp
+++ b/src/dxso/dxso_compiler.cpp
@@ -2965,7 +2965,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
         uint32_t lOffset = m_module.opAccessChain(m_module.defPointerType(float_t, spv::StorageClassUniform),
                                                   m_ps.sharedState, 1, &index);
                  lOffset = m_module.opLoad(float_t, lOffset);
-            
+
         uint32_t zIndex = 2;
         uint32_t scale = m_module.opCompositeExtract(float_t, result.id, 1, &zIndex);
                  scale = m_module.opFMul(float_t, scale, lScale);
@@ -2980,7 +2980,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
 
     auto SampleType = [&](DxsoSamplerType samplerType) {
       uint32_t bitOffset = m_programInfo.type() == DxsoProgramTypes::VertexShader
-        ? samplerIdx + caps::MaxTexturesPS + 1
+        ? samplerIdx + FirstVSSamplerSlot
         : samplerIdx;
 
       uint32_t isNull = m_spec.get(m_module, m_specUbo, SpecSamplerNull, bitOffset, 1);