Skip to content

Commit 9e1bff0

Browse files
BufferProperties: add TextureUpdateOffsetAlignment and TextureUpdateStrideAlignment (API256015)
Also fix texture updates from buffer in D3D12 and implement the path in Vulkan.
1 parent 9adebb7 commit 9e1bff0

File tree

16 files changed

+471
-37
lines changed

16 files changed

+471
-37
lines changed

Graphics/GraphicsEngine/include/DeviceContextBase.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1884,7 +1884,7 @@ inline void DeviceContextBase<ImplementationTraits>::UpdateTexture(
18841884
DEV_CHECK_ERR(pTexture != nullptr, "pTexture must not be null");
18851885
DEV_CHECK_ERR(m_pActiveRenderPass == nullptr, "UpdateTexture command must be used outside of render pass.");
18861886

1887-
ValidateUpdateTextureParams(pTexture->GetDesc(), MipLevel, Slice, DstBox, SubresData);
1887+
ValidateUpdateTextureParams(pTexture->GetDesc(), MipLevel, Slice, DstBox, SubresData, m_pDevice->GetAdapterInfo().Buffer);
18881888
++m_Stats.CommandCounters.UpdateTexture;
18891889
}
18901890

Graphics/GraphicsEngine/include/TextureBase.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ void ValidateTextureDesc(const TextureDesc& TexDesc, const IRenderDevice* pDevic
5353
void ValidatedAndCorrectTextureViewDesc(const TextureDesc& TexDesc, TextureViewDesc& ViewDesc) noexcept(false);
5454

5555
/// Validates update texture command parameters.
56-
void ValidateUpdateTextureParams(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData);
56+
void ValidateUpdateTextureParams(const TextureDesc& TexDesc,
57+
Uint32 MipLevel,
58+
Uint32 Slice,
59+
const Box& DstBox,
60+
const TextureSubResData& SubresData,
61+
const BufferProperties& BufferProps);
5762

5863
/// Validates copy texture command parameters.
5964
void ValidateCopyTextureParams(const CopyTextureAttribs& CopyAttribs);

Graphics/GraphicsEngine/interface/APIInfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2025 Diligent Graphics LLC
2+
* Copyright 2019-2026 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,7 +30,7 @@
3030
/// \file
3131
/// Diligent API information
3232

33-
#define DILIGENT_API_VERSION 256014
33+
#define DILIGENT_API_VERSION 256015
3434

3535
#include "../../../Primitives/interface/BasicTypes.h"
3636

Graphics/GraphicsEngine/interface/GraphicsTypes.h

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2228,20 +2228,35 @@ typedef struct WaveOpProperties WaveOpProperties;
22282228
/// Buffer properties
22292229
struct BufferProperties
22302230
{
2231-
/// The minimum required alignment, in bytes, for the constant buffer offsets.
2232-
2233-
/// The Offset parameter passed to IShaderResourceVariable::SetBufferRange() or to
2234-
/// IShaderResourceVariable::SetBufferOffset() method used to set the offset of a
2235-
/// constant buffer, must be an integer multiple of this limit.
2231+
/// Minimum required alignment, in bytes, for constant buffer offsets.
2232+
///
2233+
/// The `Offset` parameter passed to `IShaderResourceVariable::SetBufferRange()`
2234+
/// or `IShaderResourceVariable::SetBufferOffset()` for a constant buffer must be
2235+
/// a multiple of this value.
22362236
Uint32 ConstantBufferOffsetAlignment DEFAULT_INITIALIZER(0);
22372237

2238-
/// The minimum required alignment, in bytes, for the structured buffer offsets.
2239-
2240-
/// The ByteOffset member of the BufferViewDesc used to create a structured buffer view or
2241-
/// the Offset parameter passed to IShaderResourceVariable::SetBufferOffset() method used to
2242-
/// set the offset of a structured buffer, must be an integer multiple of this limit.
2238+
/// Minimum required alignment, in bytes, for structured buffer offsets.
2239+
///
2240+
/// The `ByteOffset` member of `BufferViewDesc` used to create a structured buffer
2241+
/// view, or the `Offset` parameter passed to
2242+
/// `IShaderResourceVariable::SetBufferOffset()` for a structured buffer, must be
2243+
/// a multiple of this value.
22432244
Uint32 StructuredBufferOffsetAlignment DEFAULT_INITIALIZER(0);
22442245

2246+
/// Minimum required alignment, in bytes, for source buffer offsets used by
2247+
/// `IDeviceContext::UpdateTexture()`.
2248+
///
2249+
/// When `TextureSubResData::pSrcBuffer` is not null, the
2250+
/// `TextureSubResData::SrcOffset` member must be a multiple of this value.
2251+
Uint32 TextureUpdateOffsetAlignment DEFAULT_INITIALIZER(0);
2252+
2253+
/// Minimum required alignment, in bytes, for source buffer row strides used by
2254+
/// `IDeviceContext::UpdateTexture()`.
2255+
///
2256+
/// When `TextureSubResData::pSrcBuffer` is not null, the
2257+
/// `TextureSubResData::Stride` member must be a multiple of this value.
2258+
Uint32 TextureUpdateStrideAlignment DEFAULT_INITIALIZER(0);
2259+
22452260
#if DILIGENT_CPP_INTERFACE
22462261
/// Comparison operator tests if two structures are equivalent
22472262

@@ -2252,10 +2267,11 @@ struct BufferProperties
22522267
constexpr bool operator==(const BufferProperties& RHS) const
22532268
{
22542269
return ConstantBufferOffsetAlignment == RHS.ConstantBufferOffsetAlignment &&
2255-
StructuredBufferOffsetAlignment == RHS.StructuredBufferOffsetAlignment;
2270+
StructuredBufferOffsetAlignment == RHS.StructuredBufferOffsetAlignment &&
2271+
TextureUpdateOffsetAlignment == RHS.TextureUpdateOffsetAlignment &&
2272+
TextureUpdateStrideAlignment == RHS.TextureUpdateStrideAlignment;
22562273
}
22572274
#endif
2258-
22592275
};
22602276
typedef struct BufferProperties BufferProperties;
22612277

Graphics/GraphicsEngine/interface/Texture.h

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2025 Diligent Graphics LLC
2+
* Copyright 2019-2026 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -274,25 +274,32 @@ typedef struct TextureDesc TextureDesc;
274274
struct TextureSubResData
275275
{
276276
/// Pointer to the subresource data in CPU memory.
277-
278-
/// If provided, `pSrcBuffer` must be null
277+
///
278+
/// If provided, `pSrcBuffer` must be null.
279279
const void* pData DEFAULT_INITIALIZER(nullptr);
280280

281-
/// Pointer to the GPU buffer that contains subresource data.
282-
283-
/// If provided, `pData` must be null
281+
/// Pointer to the GPU buffer that contains the subresource data.
282+
///
283+
/// If provided, `pData` must be null.
284284
struct IBuffer* pSrcBuffer DEFAULT_INITIALIZER(nullptr);
285285

286-
/// When updating data from the buffer (pSrcBuffer is not null),
287-
/// offset from the beginning of the buffer to the data start
286+
/// If `pSrcBuffer` is not null, offset, in bytes, from the beginning of the source
287+
/// buffer to the subresource data.
288+
///
289+
/// This value must be a multiple of `BufferProperties::TextureUpdateOffsetAlignment`,
290+
/// which can be queried through `IRenderDevice::GetAdapterInfo()`.
288291
Uint64 SrcOffset DEFAULT_INITIALIZER(0);
289292

290-
/// For 2D and 3D textures, row stride in bytes
293+
/// Row stride, in bytes, for 2D and 3D textures.
294+
///
295+
/// When `pSrcBuffer` is not null, this value must be a multiple of
296+
/// `BufferProperties::TextureUpdateStrideAlignment`, which can be queried through
297+
/// `IRenderDevice::GetAdapterInfo()`.
291298
Uint64 Stride DEFAULT_INITIALIZER(0);
292299

293-
/// For 3D textures, depth slice stride in bytes.
294-
295-
/// On OpenGL, this must be a multiple of `Stride`
300+
/// Depth slice stride, in bytes, for 3D textures.
301+
///
302+
/// On OpenGL, this value must be a multiple of `Stride`.
296303
Uint64 DepthStride DEFAULT_INITIALIZER(0);
297304

298305

Graphics/GraphicsEngine/src/TextureBase.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2025 Diligent Graphics LLC
2+
* Copyright 2019-2026 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -388,7 +388,12 @@ void ValidateTextureRegion(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 S
388388
#endif
389389
}
390390

391-
void ValidateUpdateTextureParams(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData)
391+
void ValidateUpdateTextureParams(const TextureDesc& TexDesc,
392+
Uint32 MipLevel,
393+
Uint32 Slice,
394+
const Box& DstBox,
395+
const TextureSubResData& SubresData,
396+
const BufferProperties& BufferProps)
392397
{
393398
VERIFY((SubresData.pData != nullptr) ^ (SubresData.pSrcBuffer != nullptr), "Either CPU data pointer (pData) or GPU buffer (pSrcBuffer) must not be null, but not both.");
394399
ValidateTextureRegion(TexDesc, MipLevel, Slice, DstBox);
@@ -398,6 +403,17 @@ void ValidateUpdateTextureParams(const TextureDesc& TexDesc, Uint32 MipLevel, Ui
398403
VERIFY_TEX_PARAMS((SubresData.Stride & 0x03) == 0, "Texture data stride (", SubresData.Stride, ") must be at least 32-bit aligned.");
399404
VERIFY_TEX_PARAMS((SubresData.DepthStride & 0x03) == 0, "Texture data depth stride (", SubresData.DepthStride, ") must be at least 32-bit aligned.");
400405

406+
if (SubresData.pSrcBuffer)
407+
{
408+
VERIFY_TEX_PARAMS((SubresData.SrcOffset % BufferProps.TextureUpdateOffsetAlignment) == 0,
409+
"Source buffer offset (", SubresData.SrcOffset, ") must be a multiple of device's TextureUpdateOffsetAlignment (",
410+
BufferProps.TextureUpdateOffsetAlignment, ").");
411+
412+
VERIFY_TEX_PARAMS((SubresData.Stride % BufferProps.TextureUpdateStrideAlignment) == 0,
413+
"Texture data stride (", SubresData.Stride, ") must be a multiple of device's TextureUpdateStrideAlignment (",
414+
BufferProps.TextureUpdateStrideAlignment, ").");
415+
}
416+
401417
Uint32 UpdateRegionWidth = DstBox.Width();
402418
Uint32 UpdateRegionHeight = DstBox.Height();
403419
Uint32 UpdateRegionDepth = DstBox.Depth();

Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,10 @@ GraphicsAdapterInfo EngineFactoryD3D11Impl::GetGraphicsAdapterInfo(void*
526526
// i.e. 256 bytes.
527527
BufferProps.ConstantBufferOffsetAlignment = 256;
528528
BufferProps.StructuredBufferOffsetAlignment = D3D11_RAW_UAV_SRV_BYTE_ALIGNMENT;
529-
ASSERT_SIZEOF(BufferProps, 8, "Did you add a new member to BufferProperites? Please initialize it here.");
529+
// Buffer to texture copies are not supported in D3D11
530+
BufferProps.TextureUpdateOffsetAlignment = 0;
531+
BufferProps.TextureUpdateStrideAlignment = 0;
532+
ASSERT_SIZEOF(BufferProps, 16, "Did you add a new member to BufferProperites? Please initialize it here.");
530533
}
531534

532535
// Compute shader properties

Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1963,7 +1963,7 @@ void DeviceContextD3D12Impl::UpdateTexture(ITexture* pTextu
19631963
}
19641964
else
19651965
{
1966-
CopyTextureRegion(SubresData.pSrcBuffer, 0, SubresData.Stride, SubresData.DepthStride,
1966+
CopyTextureRegion(SubresData.pSrcBuffer, SubresData.SrcOffset, SubresData.Stride, SubresData.DepthStride,
19671967
*pTexD3D12, DstSubResIndex, *pBox,
19681968
SrcBufferTransitionMode, TextureTransitionMode);
19691969
}

Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1046,7 +1046,9 @@ GraphicsAdapterInfo EngineFactoryD3D12Impl::GetGraphicsAdapterInfo(void*
10461046
BufferProperties& BufferProps{AdapterInfo.Buffer};
10471047
BufferProps.ConstantBufferOffsetAlignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
10481048
BufferProps.StructuredBufferOffsetAlignment = D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT;
1049-
ASSERT_SIZEOF(BufferProps, 8, "Did you add a new member to BufferProperites? Please initialize it here.");
1049+
BufferProps.TextureUpdateOffsetAlignment = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
1050+
BufferProps.TextureUpdateStrideAlignment = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;
1051+
ASSERT_SIZEOF(BufferProps, 16, "Did you add a new member to BufferProperites? Please initialize it here.");
10501052
}
10511053
}
10521054

Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,9 @@ void RenderDeviceGLImpl::InitAdapterInfo()
10381038
BufferProperties& BufferProps{m_AdapterInfo.Buffer};
10391039
BufferProps.ConstantBufferOffsetAlignment = 256;
10401040
BufferProps.StructuredBufferOffsetAlignment = 16;
1041-
ASSERT_SIZEOF(BufferProps, 8, "Did you add a new member to BufferProperites? Please initialize it here.");
1041+
BufferProps.TextureUpdateOffsetAlignment = 4;
1042+
BufferProps.TextureUpdateStrideAlignment = 4;
1043+
ASSERT_SIZEOF(BufferProps, 16, "Did you add a new member to BufferProperites? Please initialize it here.");
10421044
}
10431045
#undef ENABLE_FEATURE
10441046
}

0 commit comments

Comments
 (0)