Skip to content

Commit

Permalink
v1.151:
Browse files Browse the repository at this point in the history
HIGHLIGHTS:
- bug fixes and improvements

BREAKING CHANGE:
- "PipelineLayoutDesc::rootRegisterSpace" affects root constants in shaders
- added "pipelineLayout" prefix to "root" limits in "DeviceDesc" to emphasize the meaning

DETAILS:
- Helper: added optional helper "FitPipelineLayoutSettingsIntoDeviceLimits" for nerds
- Helper: removed useless "constructors" (use designated initializers)
- Core: allow "0" for "depth", "layerNum" and "sampleNum" in "TextureDesc"
- Core: added "rootRegisterSpace" to "PipelineLayoutDesc", which is used for root constants and descriptors
- bug fixes and improvements
  • Loading branch information
dzhdanNV committed Sep 20, 2024
1 parent d003e22 commit 2ab54db
Show file tree
Hide file tree
Showing 39 changed files with 626 additions and 697 deletions.
144 changes: 63 additions & 81 deletions Include/Extensions/NRIHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,96 +83,79 @@ NriStruct(HelperInterface) {
// Format utilities
NRI_API Nri(Format) NRI_CALL nriConvertDXGIFormatToNRI(uint32_t dxgiFormat);
NRI_API Nri(Format) NRI_CALL nriConvertVKFormatToNRI(uint32_t vkFormat);
NRI_API uint32_t NRI_CALL nriConvertNRIFormatToDXGI(Nri(Format) format);
NRI_API uint32_t NRI_CALL nriConvertNRIFormatToDXGI(Nri(Format) format);
NRI_API uint32_t NRI_CALL nriConvertNRIFormatToVK(Nri(Format) format);
NRI_API const NriRef(FormatProps) NRI_CALL nriGetFormatProps(Nri(Format) format);

// Strings
NRI_API const char* NRI_CALL nriGetGraphicsAPIString(Nri(GraphicsAPI) graphicsAPI);

// "TextureDesc" constructors
static inline Nri(TextureDesc) NriFunc(Texture1D)(Nri(Format) format,
uint16_t width,
Nri(Mip_t) mipNum NriDefault(1),
Nri(Dim_t) layerNum NriDefault(1),
Nri(TextureUsageBits) usageMask NriDefault(NriScopedMember(TextureUsageBits, SHADER_RESOURCE)))
{
Nri(TextureDesc) textureDesc = NriZero;
textureDesc.type = NriScopedMember(TextureType, TEXTURE_1D);
textureDesc.format = format;
textureDesc.usageMask = usageMask;
textureDesc.width = width;
textureDesc.height = 1;
textureDesc.depth = 1;
textureDesc.mipNum = mipNum;
textureDesc.layerNum = layerNum;
textureDesc.sampleNum = 1;

return textureDesc;
}
// A convinient way to fit pipeline layout settings into device limits, respecting D3D12 restrictions
NriStruct(PipelineLayoutSettingsDesc) {
uint32_t descriptorRangeNum;
uint32_t rootConstantSize;
uint32_t rootDescriptorNum;
bool preferRootDescriptorsOverConstants;
};

static inline Nri(TextureDesc) NriFunc(Texture2D)(Nri(Format) format,
Nri(Dim_t) width,
Nri(Dim_t) height,
Nri(Mip_t) mipNum NriDefault(1),
Nri(Dim_t) layerNum NriDefault(1),
Nri(TextureUsageBits) usageMask NriDefault(NriScopedMember(TextureUsageBits, SHADER_RESOURCE)),
Nri(Sample_t) sampleNum NriDefault(1))
{
Nri(TextureDesc) textureDesc = NriZero;
textureDesc.type = NriScopedMember(TextureType, TEXTURE_2D);
textureDesc.format = format;
textureDesc.usageMask = usageMask;
textureDesc.width = width;
textureDesc.height = height;
textureDesc.depth = 1;
textureDesc.mipNum = mipNum;
textureDesc.layerNum = layerNum;
textureDesc.sampleNum = sampleNum;

return textureDesc;
}
static inline Nri(PipelineLayoutSettingsDesc) NriFunc(FitPipelineLayoutSettingsIntoDeviceLimits)(const NriRef(DeviceDesc) deviceDesc, const NriRef(PipelineLayoutSettingsDesc) pipelineLayoutSettingsDesc) {
uint32_t descriptorRangeNum = NriDeref(pipelineLayoutSettingsDesc)->descriptorRangeNum;
uint32_t rootConstantSize = NriDeref(pipelineLayoutSettingsDesc)->rootConstantSize;
uint32_t rootDescriptorNum = NriDeref(pipelineLayoutSettingsDesc)->rootDescriptorNum;

static inline Nri(TextureDesc) NriFunc(Texture3D)(Nri(Format) format,
Nri(Dim_t) width,
Nri(Dim_t) height,
uint16_t depth,
Nri(Mip_t) mipNum NriDefault(1),
Nri(TextureUsageBits) usageMask NriDefault(NriScopedMember(TextureUsageBits, SHADER_RESOURCE)))
{
Nri(TextureDesc) textureDesc = NriZero;
textureDesc.type = NriScopedMember(TextureType, TEXTURE_3D);
textureDesc.format = format;
textureDesc.usageMask = usageMask;
textureDesc.width = width;
textureDesc.height = height;
textureDesc.depth = depth;
textureDesc.mipNum = mipNum;
textureDesc.layerNum = 1;
textureDesc.sampleNum = 1;

return textureDesc;
}
// Apply global limits
if (rootConstantSize > NriDeref(deviceDesc)->pipelineLayoutRootConstantMaxSize)
rootConstantSize = NriDeref(deviceDesc)->pipelineLayoutRootConstantMaxSize;

// "TextureBarrierDesc" constructors
static inline Nri(TextureBarrierDesc) NriFunc(TextureBarrier)(NriPtr(Texture) texture,
Nri(AccessLayoutStage) before,
Nri(AccessLayoutStage) after,
Nri(Mip_t) mipOffset NriDefault(0),
Nri(Mip_t) mipNum NriDefault(Nri(REMAINING_MIPS)),
Nri(Dim_t) layerOffset NriDefault(0),
Nri(Dim_t) layerNum NriDefault(Nri(REMAINING_LAYERS)))
{
Nri(TextureBarrierDesc) textureBarrierDesc = NriZero;
textureBarrierDesc.texture = texture;
textureBarrierDesc.before = before;
textureBarrierDesc.after = after;
textureBarrierDesc.mipOffset = mipOffset;
textureBarrierDesc.mipNum = mipNum;
textureBarrierDesc.layerOffset = layerOffset;
textureBarrierDesc.layerNum = layerNum;
if (rootDescriptorNum > NriDeref(deviceDesc)->pipelineLayoutRootDescriptorMaxNum)
rootDescriptorNum = NriDeref(deviceDesc)->pipelineLayoutRootDescriptorMaxNum;

return textureBarrierDesc;
// D3D12 has limited-size root signature
if (NriDeref(deviceDesc)->graphicsAPI == NriScopedMember(GraphicsAPI, D3D12)) {
const uint32_t descriptorTableCost = 4;
const uint32_t rootDescriptorCost = 8;

uint32_t freeBytesInRootSignature = 256;

// 1 root descriptor can be reserved for "draw parameters" emulation
if (NriDeref(deviceDesc)->isDrawParametersEmulationEnabled)
freeBytesInRootSignature -= 8;

// Must fit
uint32_t availableDescriptorRangeNum = freeBytesInRootSignature / descriptorTableCost;
if (descriptorRangeNum > availableDescriptorRangeNum)
descriptorRangeNum = availableDescriptorRangeNum;

freeBytesInRootSignature -= descriptorRangeNum * descriptorTableCost;

// Desired fit
if (NriDeref(pipelineLayoutSettingsDesc)->preferRootDescriptorsOverConstants) {
uint32_t availableRootDescriptorNum = freeBytesInRootSignature / rootDescriptorCost;
if (rootDescriptorNum > availableRootDescriptorNum)
rootDescriptorNum = availableRootDescriptorNum;

freeBytesInRootSignature -= rootDescriptorNum * rootDescriptorCost;

if (rootConstantSize > freeBytesInRootSignature)
rootConstantSize = freeBytesInRootSignature;
} else {
if (rootConstantSize > freeBytesInRootSignature)
rootConstantSize = freeBytesInRootSignature;

freeBytesInRootSignature -= rootConstantSize;

uint32_t availableRootDescriptorNum = freeBytesInRootSignature / rootDescriptorCost;
if (rootDescriptorNum > availableRootDescriptorNum)
rootDescriptorNum = availableRootDescriptorNum;
}
}

Nri(PipelineLayoutSettingsDesc) modifiedPipelineLayoutLimitsDesc = *NriDeref(pipelineLayoutSettingsDesc);
modifiedPipelineLayoutLimitsDesc.descriptorRangeNum = descriptorRangeNum;
modifiedPipelineLayoutLimitsDesc.rootConstantSize = rootConstantSize;
modifiedPipelineLayoutLimitsDesc.rootDescriptorNum = rootDescriptorNum;

return modifiedPipelineLayoutLimitsDesc;
}

static inline Nri(TextureBarrierDesc) NriFunc(TextureBarrierFromUnknown)(NriPtr(Texture) texture,
Expand Down Expand Up @@ -208,5 +191,4 @@ static inline Nri(TextureBarrierDesc) NriFunc(TextureBarrierFromState)(NriRef(Te

return *NriDeref(prevState);
}

NriNamespaceEnd
8 changes: 4 additions & 4 deletions Include/NRI.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ Non-goals:
#pragma once

#define NRI_VERSION_MAJOR 1
#define NRI_VERSION_MINOR 150
#define NRI_VERSION_DATE "18 September 2024"
#define NRI_VERSION_MINOR 151
#define NRI_VERSION_DATE "20 September 2024"

#include "NRIDescs.h"

Expand Down Expand Up @@ -102,8 +102,8 @@ NriStruct(CoreInterface) {
// Setup
void (NRI_CALL *CmdSetPipelineLayout) (NriRef(CommandBuffer) commandBuffer, const NriRef(PipelineLayout) pipelineLayout);
void (NRI_CALL *CmdSetDescriptorSet) (NriRef(CommandBuffer) commandBuffer, uint32_t setIndex, const NriRef(DescriptorSet) descriptorSet, const uint32_t* dynamicConstantBufferOffsets);
void (NRI_CALL *CmdSetRootConstants) (NriRef(CommandBuffer) commandBuffer, uint32_t rootConstantIndex, const void* data, uint32_t size); // requires "rootConstantMaxSize > 0"
void (NRI_CALL *CmdSetRootDescriptor) (NriRef(CommandBuffer) commandBuffer, uint32_t rootDescriptorIndex, NriRef(Descriptor) descriptor); // requires "rootDescriptorMaxNum > 0"
void (NRI_CALL *CmdSetRootConstants) (NriRef(CommandBuffer) commandBuffer, uint32_t rootConstantIndex, const void* data, uint32_t size); // requires "pipelineLayoutRootConstantMaxSize > 0"
void (NRI_CALL *CmdSetRootDescriptor) (NriRef(CommandBuffer) commandBuffer, uint32_t rootDescriptorIndex, NriRef(Descriptor) descriptor); // requires "pipelineLayoutRootDescriptorMaxNum > 0"
void (NRI_CALL *CmdSetPipeline) (NriRef(CommandBuffer) commandBuffer, const NriRef(Pipeline) pipeline);

// Barrier
Expand Down
16 changes: 9 additions & 7 deletions Include/NRICompatibility.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Push constants:
uint32_t const2;
};
NRI_ROOT_CONSTANTS(RootConstants, gRootConstants, 7); // a constant buffer in DXBC
NRI_ROOT_CONSTANTS(RootConstants, gRootConstants, 7, 0); // a constant buffer in DXBC
Draw parameters:
- Add to the global scope:
Expand All @@ -50,7 +50,8 @@ Draw parameters:
*/

#ifndef __cplusplus
#define NRI_MERGE_TOKENS(a, b) a##b
#define _NRI_MERGE_TOKENS(a, b) a##b
#define NRI_MERGE_TOKENS(a, b) _NRI_MERGE_TOKENS(a, b)
#endif

// Container detection
Expand Down Expand Up @@ -123,7 +124,7 @@ Draw parameters:
#define NRI_RESOURCE(resourceType, name, regName, bindingIndex, setIndex) \
resourceType name : register(NRI_MERGE_TOKENS(regName, bindingIndex), NRI_MERGE_TOKENS(space, setIndex))

#define NRI_ROOT_CONSTANTS(structName, name, bindingIndex) \
#define NRI_ROOT_CONSTANTS(structName, name, bindingIndex, setIndex) \
[[vk::push_constant]] structName name

// Draw parameters (full support, requires SPV_KHR_shader_draw_parameters)
Expand All @@ -140,12 +141,13 @@ Draw parameters:
#endif

// DXIL
#define NRI_BASE_ATTRIBUTES_EMULATION_SPACE 999
#ifdef NRI_DXIL
#define NRI_RESOURCE(resourceType, name, regName, bindingIndex, setIndex) \
resourceType name : register(NRI_MERGE_TOKENS(regName, bindingIndex), NRI_MERGE_TOKENS(space, setIndex))

#define NRI_ROOT_CONSTANTS(structName, name, bindingIndex) \
ConstantBuffer<structName> name : register(NRI_MERGE_TOKENS(b, bindingIndex), space0)
#define NRI_ROOT_CONSTANTS(structName, name, bindingIndex, setIndex) \
ConstantBuffer<structName> name : register(NRI_MERGE_TOKENS(b, bindingIndex), NRI_MERGE_TOKENS(space, setIndex))

// Draw parameters
#if (NRI_SHADER_MODEL < 68)
Expand All @@ -156,7 +158,7 @@ Draw parameters:
int baseVertex; \
uint baseInstance; \
}; \
ConstantBuffer<_BaseAttributeConstants> _BaseAttributes : register(b0, space999) // see BASE_ATTRIBUTES_EMULATION_SPACE
ConstantBuffer<_BaseAttributeConstants> _BaseAttributes : register(b0, NRI_MERGE_TOKENS(space, NRI_BASE_ATTRIBUTES_EMULATION_SPACE))

#define NRI_DECLARE_DRAW_PARAMETERS \
uint NRI_VERTEX_ID : SV_VertexID, \
Expand Down Expand Up @@ -202,7 +204,7 @@ Draw parameters:
#define NRI_RESOURCE(resourceType, name, regName, bindingIndex, setIndex) \
resourceType name : register(NRI_MERGE_TOKENS(regName, bindingIndex))

#define NRI_ROOT_CONSTANTS(structName, name, bindingIndex) \
#define NRI_ROOT_CONSTANTS(structName, name, bindingIndex, setIndex) \
cbuffer structName##_##name : register(NRI_MERGE_TOKENS(b, bindingIndex)) { \
structName name; \
}
Expand Down
49 changes: 26 additions & 23 deletions Include/NRIDescs.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static const Nri(Dim_t) NriConstant(REMAINING_LAYERS) = 0; // only for "layerNu

// Readability
#define NriOptional // i.e. can be 0 (keep an eye on comments)
#define NriOut // highlights output argument
#define NriOut // highlights an output argument

//============================================================================================================================================================================================
#pragma region [ Common ]
Expand Down Expand Up @@ -444,10 +444,10 @@ NriStruct(TextureDesc) {
Nri(Format) format;
Nri(Dim_t) width;
Nri(Dim_t) height;
Nri(Dim_t) depth;
NriOptional Nri(Dim_t) depth;
Nri(Mip_t) mipNum;
Nri(Dim_t) layerNum;
Nri(Sample_t) sampleNum;
NriOptional Nri(Dim_t) layerNum;
NriOptional Nri(Sample_t) sampleNum;
};

NriStruct(BufferDesc) {
Expand Down Expand Up @@ -549,8 +549,8 @@ Pipeline layout example:
RootConstantDesc #0 // "rootConstantIndex" - an index in "rootConstants" in the currently bound pipeline layout
RootDescriptorSetDesc #0 // "rootDescriptorIndex" - an index in "rootDescriptorSets" in the currently bound pipeline layout
RootDescriptorSetDesc #1
RootDescriptorDesc #0 // "rootDescriptorIndex" - an index in "rootDescriptors" in the currently bound pipeline layout
RootDescriptorDesc #1
*/

// "DescriptorRange" consists of "Descriptor" entities
Expand All @@ -576,34 +576,34 @@ NriStruct(DynamicConstantBufferDesc) {
};

NriStruct(DescriptorSetDesc) {
uint32_t registerSpace;
uint32_t registerSpace; // must be unique, avoid big gaps
const NriPtr(DescriptorRangeDesc) ranges;
uint32_t rangeNum;
const NriPtr(DynamicConstantBufferDesc) dynamicConstantBuffers; // a dynamic constant buffer allows to dynamically specify an offset in the buffer via "CmdSetDescriptorSet" call
uint32_t dynamicConstantBufferNum;
};

// "PipelineLayout" consists of "DescriptorSet" descriptions and root parameters
NriStruct(RootConstantDesc) { // aka push constants
NriStruct(RootConstantDesc) { // aka push constants block
uint32_t registerIndex;
uint32_t size;
Nri(StageBits) shaderStages;
};

NriStruct(RootDescriptorSetDesc) { // aka push descriptor
uint32_t registerSpace;
NriStruct(RootDescriptorDesc) { // aka push descriptor
uint32_t registerIndex;
Nri(DescriptorType) descriptorType; // CONSTANT_BUFFER, STRUCTURED_BUFFER or STORAGE_STRUCTURED_BUFFER
Nri(StageBits) shaderStages;
};

NriStruct(PipelineLayoutDesc) {
const NriPtr(DescriptorSetDesc) descriptorSets;
uint32_t descriptorSetNum;
uint32_t rootRegisterSpace;
const NriPtr(RootConstantDesc) rootConstants;
uint32_t rootConstantNum;
const NriPtr(RootDescriptorSetDesc) rootDescriptorSets;
uint32_t rootDescriptorSetNum;
const NriPtr(RootDescriptorDesc) rootDescriptors;
uint32_t rootDescriptorNum;
const NriPtr(DescriptorSetDesc) descriptorSets;
uint32_t descriptorSetNum;
Nri(StageBits) shaderStages;
bool ignoreGlobalSPIRVOffsets;
bool enableD3D12DrawParametersEmulation; // implicitly expects "enableD3D12DrawParametersEmulation" passed during device creation
Expand Down Expand Up @@ -1319,7 +1319,7 @@ NriStruct(DeviceDesc) {
Nri(Dim_t) texture2DMaxDim;
Nri(Dim_t) texture3DMaxDim;
Nri(Dim_t) textureArrayLayerMaxNum;
uint32_t texelBufferMaxDim;
uint32_t typedBufferMaxDim;

// Memory
uint64_t deviceUploadHeapSize; // ReBAR
Expand All @@ -1340,15 +1340,10 @@ NriStruct(DeviceDesc) {
uint32_t rayTracingScratchAlignment;

// Pipeline layout
// D3D12 only: rootConstantSize + descriptorSetNum * 4 + rootDescriptorNum * 8 <= 256 (see "FitPipelineLayoutSettingsIntoDeviceLimits")
uint32_t pipelineLayoutDescriptorSetMaxNum;
uint32_t perStageDescriptorSamplerMaxNum;
uint32_t perStageDescriptorConstantBufferMaxNum;
uint32_t perStageDescriptorStorageBufferMaxNum;
uint32_t perStageDescriptorTextureMaxNum;
uint32_t perStageDescriptorStorageTextureMaxNum;
uint32_t perStageResourceMaxNum;
uint32_t rootConstantMaxSize;
uint32_t rootDescriptorMaxNum;
uint32_t pipelineLayoutRootConstantMaxSize;
uint32_t pipelineLayoutRootDescriptorMaxNum;

// Descriptor set
uint32_t descriptorSetSamplerMaxNum;
Expand All @@ -1357,6 +1352,14 @@ NriStruct(DeviceDesc) {
uint32_t descriptorSetTextureMaxNum;
uint32_t descriptorSetStorageTextureMaxNum;

// Shader resources
uint32_t perStageDescriptorSamplerMaxNum;
uint32_t perStageDescriptorConstantBufferMaxNum;
uint32_t perStageDescriptorStorageBufferMaxNum;
uint32_t perStageDescriptorTextureMaxNum;
uint32_t perStageDescriptorStorageTextureMaxNum;
uint32_t perStageResourceMaxNum;

// Vertex shader
uint32_t vertexShaderAttributeMaxNum;
uint32_t vertexShaderStreamMaxNum;
Expand Down
2 changes: 1 addition & 1 deletion Resources/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#define STR(x) STR_HELPER(x)

#define VERSION_MAJOR 1
#define VERSION_MINOR 150
#define VERSION_MINOR 151
#define VERSION_BUILD 0
#define VERSION_REVISION 0

Expand Down
4 changes: 2 additions & 2 deletions Source/Creation/Creation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,11 +431,11 @@ NRI_API Result NRI_CALL nriEnumerateAdapters(AdapterDesc* adapterDescs, uint32_t
if (result == VK_SUCCESS && deviceGroupNum) {
if (adapterDescs) {
// Query device groups
VkPhysicalDeviceGroupProperties* deviceGroupProperties = StackAlloc(VkPhysicalDeviceGroupProperties, deviceGroupNum);
VkPhysicalDeviceGroupProperties* deviceGroupProperties = AllocateScratch(m_Device, VkPhysicalDeviceGroupProperties, deviceGroupNum);
vkEnumeratePhysicalDeviceGroups(instance, &deviceGroupNum, deviceGroupProperties);

// Query device groups properties
AdapterDesc* adapterDescsSorted = StackAlloc(AdapterDesc, deviceGroupNum);
AdapterDesc* adapterDescsSorted = AllocateScratch(m_Device, AdapterDesc, deviceGroupNum);
for (uint32_t i = 0; i < deviceGroupNum; i++) {
VkPhysicalDeviceIDProperties deviceIDProperties = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES};
VkPhysicalDeviceProperties2 properties2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
Expand Down
Loading

0 comments on commit 2ab54db

Please sign in to comment.