DirectX-Specs

D3D12 Revised Create Views

Version 1.0


Contents


Background

Historically, D3D12 APIs for creating buffer views—such as ID3D12Device::CreateShaderResourceView and ID3D12Device::CreateUnorderedAccessView—were limited to element-based offsets rather than byte offsets. This approach constrained flexibility, particularly when suballocating buffers with non-power of 2 formats. As a result, applications often encountered challenges managing buffers whose sizes did not align with expected format types, leading to inefficient resource utilization and increased complexity.

With this revision, D3D12 now supports buffer views defined by byte offsets and sizes, aligning its capabilities with those already present in APIs like Vulkan. This enhancement enables more precise suballocation and resource management, leveraging hardware support that is already widely available. Additionally, the updated APIs provide improved error reporting through HRESULT return values, allowing developers to diagnose failures more effectively without relying on device removal as the sole indicator of issues.

This specification documents the completed changes that address both the flexibility of buffer view creation and the robustness of error handling in D3D12.


Detailed Design

API Design

Summary of Proposed API Changes:


ID3D12Device16

These new methods are available in ID3D12Device16 interfaces or newer

class ID3D12Device16 : public ID3D12Device15
{
public:
    virtual HRESULT TryCreateShaderResourceView(
        ID3D12Resource* pResource,
        const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,
        D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
    ) = 0;

    virtual HRESULT TryCreateUnorderedAccessView(
        ID3D12Resource* pResource,
        ID3D12Resource* pCounterResource,
        const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,
        D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
    ) = 0;

    virtual HRESULT TryCreateConstantBufferView(
        const D3D12_CONSTANT_BUFFER_VIEW_DESC* pDesc,
        D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
    ) = 0;

    virtual HRESULT TryCreateSampler2(
        const D3D12_SAMPLER_DESC2* pDesc,
        D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
    ) = 0;

    virtual HRESULT TryCreateRenderTargetView(
        ID3D12Resource* pResource,
        const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,
        D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
    ) = 0;

    virtual HRESULT TryCreateDepthStencilView(
        ID3D12Resource* pResource,
        const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,
        D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
    ) = 0;

    virtual HRESULT TryCreateSamplerFeedbackUnorderedAccessView(
        ID3D12Resource* pTargetedResource,
        ID3D12Resource* pFeedbackResource,
        D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
    ) = 0;
};

Feature Check D3D12_FEATURE_DATA_D3D12_OPTIONS22.CreateByteOffsetViewsSupported

Applications can check for the support for creating views based on byte offset with the following check. This will return true when the driver DDI is above 121, and false if not.

typedef 
enum D3D12_FEATURE
    {
        // ... removed for brevity
        D3D12_FEATURE_DATA_D3D12_OPTIONS22	= 65 // Options 22
    } 	D3D12_FEATURE;

    typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS22
    {
        //... removed for brevity
        _Out_  BOOL CreateByteOffsetViewsSupported;
    } 	D3D12_FEATURE_DATA_D3D12_OPTIONS22;

    // Example usage
bool CheckFeatureSupport()
{
    // m_Device is ID3D12Device
    D3D12_FEATURE_DATA_D3D12_OPTIONS22 createByteOffset = {};
    HRESULT hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS22,
        &createByteOffset, sizeof(createByteOffset));
    
    if (FAILED(hr)) {
        WEX::Logging::Log::Comment(L"Failed to query D3D12_FEATURE_CREATE_BYTE_OFFSET_VIEWS");
        return false;
    }
    
    return createByteOffset.CreateByteOffsetViewsSupported;
}

D3D12_SRV_DIMENSION_BUFFER_BYTE_OFFSET

A new member value for D3D12_SHADER_RESOURCE_VIEW_DESC::ViewDimension. When specified, D3D12_SHADER_RESOURCE_VIEW_DESC::BufferByteOffset is used for determining the dimension of the view.

typedef 
enum D3D12_SRV_DIMENSION
{
    D3D12_SRV_DIMENSION_UNKNOWN = 0,
    D3D12_SRV_DIMENSION_BUFFER = 1,
    D3D12_SRV_DIMENSION_TEXTURE1D = 2,
    D3D12_SRV_DIMENSION_TEXTURE1DARRAY = 3,
    D3D12_SRV_DIMENSION_TEXTURE2D = 4,
    D3D12_SRV_DIMENSION_TEXTURE2DARRAY = 5,
    D3D12_SRV_DIMENSION_TEXTURE2DMS = 6,
    D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY = 7,
    D3D12_SRV_DIMENSION_TEXTURE3D = 8,
    D3D12_SRV_DIMENSION_TEXTURECUBE = 9,
    D3D12_SRV_DIMENSION_TEXTURECUBEARRAY = 10,
    D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE = 11,
    D3D12_SRV_DIMENSION_BUFFER_BYTE_OFFSET = 12 // <--- New field
} D3D12_SRV_DIMENSION;

D3D12_BUFFER_SRV_BYTE_OFFSET

Used by D3D12_SHADER_RESOURCE_VIEW_DESC in conjunction with the new enum member D3D12_SRV_DIMENSION_BUFFER_BYTE_OFFSET.

typedef struct D3D12_BUFFER_SRV_BYTE_OFFSET
{
  UINT64 Offset;
  UINT64 Size;
  UINT StructureByteStride;
  D3D12_BUFFER_SRV_FLAGS Flags;
} D3D12_BUFFER_SRV_BYTE_OFFSET;

Members:


D3D12_SHADER_RESOURCE_VIEW_DESC

This remains the same as the MSDN documentation, with a newly added member in the union, BufferByteOffset.

typedef struct D3D12_SHADER_RESOURCE_VIEW_DESC
{
  DXGI_FORMAT Format;
  D3D12_SRV_DIMENSION ViewDimension;
  UINT Shader4ComponentMapping;
  union 
    {
        D3D12_BUFFER_SRV Buffer;
        D3D12_TEX1D_SRV Texture1D;
        D3D12_TEX1D_ARRAY_SRV Texture1DArray;
        D3D12_TEX2D_SRV Texture2D;
        D3D12_TEX2D_ARRAY_SRV Texture2DArray;
        D3D12_TEX2DMS_SRV Texture2DMS;
        D3D12_TEX2DMS_ARRAY_SRV Texture2DMSArray;
        D3D12_TEX3D_SRV Texture3D;
        D3D12_TEXCUBE_SRV TextureCube;
        D3D12_TEXCUBE_ARRAY_SRV TextureCubeArray;
        D3D12_RAYTRACING_ACCELERATION_STRUCTURE_SRV RaytracingAccelerationStructure;
        D3D12_BUFFER_SRV_BYTE_OFFSET BufferByteOffset; // <--- New Field
    };
} D3D12_SHADER_RESOURCE_VIEW_DESC;

TryCreateShaderResourceView

HRESULT ID3D12DeviceExtended::TryCreateShaderResourceView(
  ID3D12Resource                        *pResource,
  const D3D12_SHADER_RESOURCE_VIEW_DESC *pDesc,
  D3D12_CPU_DESCRIPTOR_HANDLE           DestDescriptor
);

A revved version of CreateShaderResourceView that returns an HRESULT for improved error reporting and validation. The parameters and descriptor structure remain unchanged.

Supported return values:


D3D12_UAV_DIMENSION_BUFFER_BYTE_OFFSET

A new member value for D3D12_UNORDERED_ACCESS_VIEW_DESC::ViewDimension. When specified, D3D12_UNORDERED_ACCESS_VIEW_DESC::BufferByteOffset is used for determining the dimension of the view.

typedef 
enum D3D12_UAV_DIMENSION
{
    D3D12_UAV_DIMENSION_UNKNOWN = 0,
    D3D12_UAV_DIMENSION_BUFFER = 1,
    D3D12_UAV_DIMENSION_TEXTURE1D = 2,
    D3D12_UAV_DIMENSION_TEXTURE1DARRAY = 3,
    D3D12_UAV_DIMENSION_TEXTURE2D = 4,
    D3D12_UAV_DIMENSION_TEXTURE2DARRAY = 5,
    D3D12_UAV_DIMENSION_TEXTURE2DMS = 6,
    D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY = 7,
    D3D12_UAV_DIMENSION_TEXTURE3D = 8,
    D3D12_UAV_DIMENSION_BUFFER_BYTE_OFFSET = 9 // <--- New field
} D3D12_UAV_DIMENSION;

D3D12_BUFFER_UAV_BYTE_OFFSET

Used by D3D12_UNORDERED_ACCESS_VIEW_DESC in conjunction with the new enum member D3D12_UAV_DIMENSION_BUFFER_BYTE_OFFSET.

typedef struct D3D12_BUFFER_UAV_BYTE_OFFSET
{
  UINT64 Offset;
  UINT64 Size;
  UINT StructureByteStride;
  UINT64 CounterOffsetInBytes;
  D3D12_BUFFER_UAV_FLAGS Flags;
} D3D12_BUFFER_UAV_BYTE_OFFSET;

Members:


D3D12_UNORDERED_ACCESS_VIEW_DESC

This remains the same as the MSDN documentation, with a newly added member in the union, BufferByteOffset.

typedef struct D3D12_UNORDERED_ACCESS_VIEW_DESC
{
  DXGI_FORMAT Format;
  D3D12_UAV_DIMENSION ViewDimension;
  union 
    {
      D3D12_BUFFER_UAV Buffer;
      D3D12_TEX1D_UAV Texture1D;
      D3D12_TEX1D_ARRAY_UAV Texture1DArray;
      D3D12_TEX2D_UAV Texture2D;
      D3D12_TEX2D_ARRAY_UAV Texture2DArray;
      D3D12_TEX3D_UAV Texture3D;
      D3D12_BUFFER_UAV_BYTE_OFFSET BufferByteOffset; // <--- New Field
    };
} D3D12_UNORDERED_ACCESS_VIEW_DESC;

TryCreateUnorderedAccessView

HRESULT ID3D12DeviceExtended::TryCreateUnorderedAccessView(
  ID3D12Resource                        *pResource,
  ID3D12Resource                        *pCounterResource,
  const D3D12_UNORDERED_ACCESS_VIEW_DESC *pDesc,
  D3D12_CPU_DESCRIPTOR_HANDLE           DestDescriptor
);

A revved version of CreateUnorderedAccessView that returns an HRESULT for improved error reporting and validation. The parameters and descriptor structure remain unchanged.

Supported return values:

TryCreateConstantBufferView

HRESULT ID3D12DeviceExtended::TryCreateConstantBufferView(
  const D3D12_CONSTANT_BUFFER_VIEW_DESC* pDesc,
  D3D12_CPU_DESCRIPTOR_HANDLE            DestDescriptor
);

A revved version of CreateConstantBufferView that returns an HRESULT for improved error reporting and validation. The parameters and descriptor structure remain unchanged.

Supported return values:


TryCreateSampler2

HRESULT ID3D12DeviceExtended::TryCreateSampler2(
  const D3D12_SAMPLER_DESC2*   pDesc,
  D3D12_CPU_DESCRIPTOR_HANDLE  DestDescriptor
);

A revved version of CreateSampler2 that returns an HRESULT for improved error reporting and validation. The parameters and descriptor structure remain unchanged.

Supported return values:


TryCreateRenderTargetView

HRESULT ID3D12DeviceExtended::TryCreateRenderTargetView(
  ID3D12Resource*                      pResource,
  const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,
  D3D12_CPU_DESCRIPTOR_HANDLE          DestDescriptor
);

A revved version of CreateRenderTargetView that returns an HRESULT for improved error reporting and validation. The parameters and descriptor structure remain unchanged.

Supported return values:


TryCreateDepthStencilView

HRESULT ID3D12DeviceExtended::TryCreateDepthStencilView(
  ID3D12Resource*                      pResource,
  const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,
  D3D12_CPU_DESCRIPTOR_HANDLE          DestDescriptor
);

A revved version of CreateDepthStencilView that returns an HRESULT for improved error reporting and validation. The parameters and descriptor structure remain unchanged.

Supported return values:


TryCreateSamplerFeedbackUnorderedAccessView

HRESULT ID3D12DeviceExtended::TryCreateSamplerFeedbackUnorderedAccessView(
  ID3D12Resource              *pTargetedResource,
  ID3D12Resource              *pFeedbackResource,
  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
);

A revved version of CreateSamplerFeedbackUnorderedAccessView that returns an HRESULT for improved error reporting and validation. The parameters and descriptor structure remain unchanged.

Supported return values:


D3D12.h Changes

This lists all the changes to d3d12.h

// d3d12.h

//
// SRV changes
//

// New struct
typedef struct D3D12_BUFFER_SRV_BYTE_OFFSET
{
  UINT64 Offset;
  UINT64 Size;
  UINT StructureByteStride;
  D3D12_BUFFER_SRV_FLAGS Flags;
} D3D12_BUFFER_SRV_BYTE_OFFSET;

// Added a new element to enum
typedef 
enum D3D12_SRV_DIMENSION
{
    D3D12_SRV_DIMENSION_UNKNOWN = 0,
    D3D12_SRV_DIMENSION_BUFFER = 1,
    // ... removed for brevity
    D3D12_SRV_DIMENSION_BUFFER_BYTE_OFFSET = 12 // <--- New field
} D3D12_SRV_DIMENSION;

// New union member BufferByteOffset
typedef struct D3D12_SHADER_RESOURCE_VIEW_DESC
{
  DXGI_FORMAT Format;
  D3D12_SRV_DIMENSION ViewDimension; // Set this to D3D12_SRV_DIMENSION_BUFFER_BYTE_OFFSET for using bytes
  UINT Shader4ComponentMapping;
  union 
    {
      // ... Removed for brevity
      D3D12_BUFFER_SRV_BYTE_OFFSET BufferByteOffset; // <--- New Field
    };
} D3D12_SHADER_RESOURCE_VIEW_DESC;

//
// UAV changes
//

// New struct
typedef struct D3D12_BUFFER_UAV_BYTE_OFFSET
{
  UINT64 Offset;
  UINT64 Size;
  UINT StructureByteStride;
  UINT64 CounterOffsetInBytes;
  D3D12_BUFFER_UAV_FLAGS Flags;
} D3D12_BUFFER_UAV_BYTE_OFFSET;

// Added a new element to enum
typedef 
enum D3D12_UAV_DIMENSION
{
    D3D12_UAV_DIMENSION_UNKNOWN = 0,
    D3D12_UAV_DIMENSION_BUFFER = 1,
    // ... removed for brevity
    D3D12_UAV_DIMENSION_BUFFER_BYTE_OFFSET = 9 // <--- New field
} D3D12_UAV_DIMENSION;

typedef struct D3D12_UNORDERED_ACCESS_VIEW_DESC
{
  DXGI_FORMAT Format;
  D3D12_UAV_DIMENSION ViewDimension;
  union 
    {
      // ... Removed for brevity
      D3D12_BUFFER_UAV_BYTE_OFFSET BufferByteOffset; // <--- New Field
    };
};

// New ID3D12Device with newly revved methods
class ID3D12DeviceExtended : public ID3D12Device14
{
public:
  HRESULT TryCreateShaderResourceView(
    ID3D12Resource* pResource,
    const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,
    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
  );

  HRESULT TryCreateUnorderedAccessView(
    ID3D12Resource* pResource,
    ID3D12Resource* pCounterResource,
    const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,
    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
  );

  HRESULT TryCreateConstantBufferView(
    const D3D12_CONSTANT_BUFFER_VIEW_DESC* pDesc,
    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
  );

  HRESULT TryCreateSampler2(
    const D3D12_SAMPLER_DESC2* pDesc,
    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
  );

  HRESULT TryCreateRenderTargetView(
    ID3D12Resource* pResource,
    const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,
    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
  );

  HRESULT TryCreateDepthStencilView(
    ID3D12Resource* pResource,
    const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,
    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
  );

  HRESULT TryCreateSamplerFeedbackUnorderedAccessView(
        ID3D12Resource* pTargetedResource,
        ID3D12Resource* pFeedbackResource,
        D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
  );
};

DDI Design

The DDI design closely mirrors the API design, but there are no changes for allowing driver error reporting. Given that most of the D3D12DDIARG_CREATE_thing_VIEW struct sizes are not changing, only UAV creation methods will be revved. Drivers report support via the newly revved D3D12DDI_D3D12_OPTIONS_DATA_0121::ViewCreationByteOffsetSupported.

If the driver DDI version is greater than or equal to 121, the runtime will call the new DDI method instead of the old one.


DDI Changes

//
// Common changes
//

// d3d12umddi.h

typedef enum D3D12DDI_RESOURCE_DIMENSION
{
    D3D12DDI_RD_BUFFER      = 1,
    D3D12DDI_RD_TEXTURE1D   = 2,
    D3D12DDI_RD_TEXTURE2D   = 3,
    D3D12DDI_RD_TEXTURE3D   = 4,
    D3D12DDI_RD_TEXTURECUBE = 5,
    D3D12DDI_RD_RAYTRACING_ACCELERATION_STRUCTURE_0042 = 6,
    D3D12DDI_RD_BUFFER_BYTE_OFFSET_0121 = 7, // --- New field
} D3D12DDI_RESOURCE_DIMENSION;

//
//  Changes for SRV creation
//

// New struct
typedef struct D3D12DDIARG_BUFFER_BYTE_OFFSET_SHADER_RESOURCE_VIEW_0121
{
    UINT64 Offset;
    UINT64 Size;
    UINT StructureByteStride; 
    D3D12DDI_BUFFER_SRV_FLAGS Flags;
} D3D12DDIARG_BUFFER_BYTE_OFFSET_SHADER_RESOURCE_VIEW_0121;

// Add a new member to this struct (size of struct stays the same)
typedef struct D3D12DDIARG_CREATE_SHADER_RESOURCE_VIEW_0002
{
    D3D12DDI_HRESOURCE    hDrvResource;
    DXGI_FORMAT           Format;
    D3D12DDI_RESOURCE_DIMENSION ResourceDimension; // Allows new usage of D3D12DDI_RD_BUFFER_BYTE_OFFSET_0121
    UINT                  Shader4ComponentMapping;

    union
    {
        D3D12DDIARG_BUFFER_SHADER_RESOURCE_VIEW                                 Buffer;
        D3D12DDIARG_TEX1D_SHADER_RESOURCE_VIEW                                  Tex1D;
        D3D12DDIARG_TEX2D_SHADER_RESOURCE_VIEW_0002                             Tex2D;
        D3D12DDIARG_TEX3D_SHADER_RESOURCE_VIEW                                  Tex3D;
        D3D12DDIARG_TEXCUBE_SHADER_RESOURCE_VIEW                                TexCube;
        D3D12DDIARG_RAYTRACING_ACCELERATION_STRUCTURE_SHADER_RESOURCE_VIEW_0042 RaytracingAccelerationStructure;
        D3D12DDIARG_BUFFER_BYTE_OFFSET_SHADER_RESOURCE_VIEW_0121                     BufferByteOffset; // --- New field
    };
} D3D12DDIARG_CREATE_SHADER_RESOURCE_VIEW_0002;

//
//  Changes for UAV creation
//

// New struct
typedef struct D3D12DDIARG_BUFFER_OFFSET_BYTE_UNORDERED_ACCESS_VIEW_0121
{
    D3D12DDI_HRESOURCE        hDrvCounterResource; 
    UINT64                    Offset;
    UINT64                    Size;
    UINT64                    CounterOffsetInBytes;
    UINT                      StructureByteStride; 
    D3D12DDI_BUFFER_UAV_FLAGS Flags;
} D3D12DDIARG_BUFFER_OFFSET_BYTE_UNORDERED_ACCESS_VIEW_0121;

// Revved from D3D12DDIARG_CREATE_UNORDERED_ACCESS_VIEW_0002
typedef struct D3D12DDIARG_CREATE_UNORDERED_ACCESS_VIEW_0121
{
    D3D12DDI_HRESOURCE    hDrvResource;
    DXGI_FORMAT           Format;                 
    D3D12DDI_RESOURCE_DIMENSION ResourceDimension; // Allows new usage of D3D12DDI_RD_BUFFER_BYTE_OFFSET_0121
    union
    {
        D3D12DDIARG_BUFFER_UNORDERED_ACCESS_VIEW            Buffer;
        D3D12DDIARG_TEX1D_UNORDERED_ACCESS_VIEW             Tex1D;
        D3D12DDIARG_TEX2D_UNORDERED_ACCESS_VIEW_0002        Tex2D;
        D3D12DDIARG_TEX3D_UNORDERED_ACCESS_VIEW             Tex3D;
        D3D12DDIARG_BUFFER_OFFSET_BYTE_UNORDERED_ACCESS_VIEW_0121 BufferByteOffset; // --- New field
    };
} D3D12DDIARG_CREATE_UNORDERED_ACCESS_VIEW_0121;

// Revved from PFND3D12DDI_CREATE_UNORDERED_ACCESS_VIEW_0002
typedef void ( APIENTRY* PFND3D12DDI_CREATE_UNORDERED_ACCESS_VIEW_0121 )( D3D12DDI_HDEVICE, _In_ CONST D3D12DDIARG_CREATE_UNORDERED_ACCESS_VIEW_0121 *, _In_ D3D12DDI_CPU_DESCRIPTOR_HANDLE DestDescriptor );

//
// Core functionality revs
//

// Revved from D3D12DDI_DEVICE_FUNCS_CORE_0116
typedef struct D3D12DDI_DEVICE_FUNCS_CORE_0121
{
  // ... Removed for brevity
  PFND3D12DDI_CREATE_UNORDERED_ACCESS_VIEW_0121   pfnCreateUnorderedAccessView; // Only the create UAV needs to be revved
} D3D12DDI_DEVICE_FUNCS_CORE_0121;

// Revved from D3D12DDI_D3D12_OPTIONS_DATA_0089, used to report support
typedef struct D3D12DDI_D3D12_OPTIONS_DATA_0121
{
    // Same as D3D12DDI_D3D12_OPTIONS_DATA_0089
    BOOL ViewCreationByteOffsetSupported;
} D3D12DDI_D3D12_OPTIONS_DATA_0121;

Runtime validation

The following validation will be performed by the runtime:

The example below demonstrates the relationship between the offset alignment rules with a given HLSL structured buffer

// In the HLSL file...
struct A { uint16_t x, y; }; // Size of 4 bytes, aligned by 2
StructuredBuffer<A> mySB;

struct B { uint64_t x; uint16_t y; }; // size of 16 bytes, aligned by 8

  // Somewhere in C++ code when creating views
  // Creating a view of Struct A
  D3D12_SHADER_RESOURCE_VIEW_DESC srvDescA = {};
  srvDescA.Format = DXGI_FORMAT_UNKNOWN; // Specify structured buffer 
  srvDescA.ViewDimension = D3D12_SRV_DIMENSION_BUFFER_BYTE_OFFSET;
  srvDescA.BufferByteOffset.Offset = 4; // Since size is 4, this offset must be aligned by 4 based on the Validation rules above for structured buffers
  srvDescA.BufferByteOffset.Size = 4 * 16; // Size must be a multiple of StructureByteStride
  srvDescA.BufferByteOffset.StructureByteStride = 4;

  ID3D12DeviceExtended* extendedDevice;
  pDevice->QueryInterface(&extendedDevice); // Convert ID3D12Device to ID3D12DeviceExtended
  if(extendedDevice->TryCreateShaderViewResource(pResource, nullptr, &srvDescA, heap->GetCPUDescriptorHandleForHeapStart()) != S_OK)
  {
    // Error
  }
  if(extendedDevice->TryCreateShaderViewResource(pResource, nullptr, &srvDescB, heap->GetCPUDescriptorHandleForHeapStart()) != S_OK)
  {
    // Error
  }

  ---

## Example Usage

Below is a complete example demonstrating how to create a shader resource view with byte offset using the new API:

```cpp
// Assume pDevice is a valid ID3D12Device pointer
ID3D12DeviceExtended* pDeviceExtended = nullptr;
HRESULT hr = pDevice->QueryInterface(IID_PPV_ARGS(&pDeviceExtended));
if (SUCCEEDED(hr))
{
  D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  srvDesc.Format = DXGI_FORMAT_UNKNOWN;
  srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER_BYTE_OFFSET;
  srvDesc.BufferByteOffset.Offset = 64; // 64-byte offset
  srvDesc.BufferByteOffset.Size = 256;  // 256 bytes
  srvDesc.BufferByteOffset.StructureByteStride = 16; // Structured buffer, 16 bytes per element
  srvDesc.BufferByteOffset.Flags = D3D12_BUFFER_SRV_FLAG_NONE;

  D3D12_CPU_DESCRIPTOR_HANDLE handle = heap->GetCPUDescriptorHandleForHeapStart();
  hr = pDeviceExtended->TryCreateShaderResourceView(pResource, &srvDesc, handle);
  if (FAILED(hr))
  {
    // Handle error
  }
  pDeviceExtended->Release();
}

Debug layer validation


Changelog