Skip to content

Commit

Permalink
V1.3.0 (#52)
Browse files Browse the repository at this point in the history
* Adding support for configurable alpha cutoff condition for greater flexibility to implement OIT and particle effects
  • Loading branch information
nv-jdeligiannis authored Jul 10, 2024
1 parent 948f07d commit 01fdb76
Show file tree
Hide file tree
Showing 19 changed files with 447 additions and 197 deletions.
20 changes: 16 additions & 4 deletions integration/omm-sdk-nvrhi/omm-sdk-nvrhi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class GpuBakeNvrhiImpl
{
public:

GpuBakeNvrhiImpl(nvrhi::DeviceHandle device, nvrhi::CommandListHandle commandList, bool enableDebug, GpuBakeNvrhi::ShaderProvider* shaderProvider);
GpuBakeNvrhiImpl(nvrhi::DeviceHandle device, nvrhi::CommandListHandle commandList, bool enableDebug, GpuBakeNvrhi::ShaderProvider* shaderProvider, std::optional<GpuBakeNvrhi::MessageCallback> messageCallback);
~GpuBakeNvrhiImpl();

// CPU side pre-build info.
Expand Down Expand Up @@ -263,12 +263,14 @@ class GpuBakeNvrhiImpl
omm::Baker m_cpuBaker;
omm::Gpu::Pipeline m_pipeline;
bool m_enableDebug = false;
std::optional<GpuBakeNvrhi::MessageCallback> m_messageCallback;
};

GpuBakeNvrhiImpl::GpuBakeNvrhiImpl(nvrhi::DeviceHandle device, nvrhi::CommandListHandle commandList, bool enableDebug, GpuBakeNvrhi::ShaderProvider* shaderProvider)
GpuBakeNvrhiImpl::GpuBakeNvrhiImpl(nvrhi::DeviceHandle device, nvrhi::CommandListHandle commandList, bool enableDebug, GpuBakeNvrhi::ShaderProvider* shaderProvider, std::optional<GpuBakeNvrhi::MessageCallback> messageCallback)
: m_device(device)
, m_bindingCache(new BindingCache(device))
, m_enableDebug(enableDebug)
, m_messageCallback(messageCallback)
{
InitStaticBuffers(commandList);
InitBaker(shaderProvider);
Expand Down Expand Up @@ -369,6 +371,14 @@ void GpuBakeNvrhiImpl::InitBaker(GpuBakeNvrhi::ShaderProvider* shaderProvider)
{
omm::BakerCreationDesc desc;
desc.type = omm::BakerType::GPU;
if (m_messageCallback.has_value())
{
desc.messageInterface.userArg = this;
desc.messageInterface.messageCallback = [](omm::MessageSeverity severity, const char* message, void* userArg) {
GpuBakeNvrhiImpl* _this = (GpuBakeNvrhiImpl*)userArg;
_this->m_messageCallback.value()(severity, message);
};
}

omm::Result res = omm::CreateBaker(desc, &m_baker);
assert(res == omm::Result::SUCCESS);
Expand Down Expand Up @@ -665,6 +675,8 @@ omm::Gpu::DispatchConfigDesc GpuBakeNvrhiImpl::GetConfig(const GpuBakeNvrhi::Inp
config.alphaTextureChannel = params.alphaTextureChannel;
config.alphaMode = AlphaMode::Test;
config.alphaCutoff = params.alphaCutoff;
config.alphaCutoffGT = params.alphaCutoffGT;
config.alphaCutoffLE = params.alphaCutoffLE;
config.texCoordFormat = GetTexCoordFormat(params.texCoordFormat);
config.texCoordOffsetInBytes = params.texCoordBufferOffsetInBytes;
config.texCoordStrideInBytes = params.texCoordStrideInBytes;
Expand Down Expand Up @@ -1205,8 +1217,8 @@ GpuBakeNvrhi::Stats GpuBakeNvrhiImpl::GetStats(const omm::Cpu::BakeResultDesc& d
}


GpuBakeNvrhi::GpuBakeNvrhi(nvrhi::DeviceHandle device, nvrhi::CommandListHandle commandList, bool enableDebug, ShaderProvider* shaderProvider)
:m_impl(std::make_unique<GpuBakeNvrhiImpl>(device, commandList, enableDebug, shaderProvider))
GpuBakeNvrhi::GpuBakeNvrhi(nvrhi::DeviceHandle device, nvrhi::CommandListHandle commandList, bool enableDebug, ShaderProvider* shaderProvider, std::optional<MessageCallback> callback)
:m_impl(std::make_unique<GpuBakeNvrhiImpl>(device, commandList, enableDebug, shaderProvider, callback))
{

}
Expand Down
7 changes: 6 additions & 1 deletion integration/omm-sdk-nvrhi/omm-sdk-nvrhi.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
#include <functional>
#include <vector>
#include <memory>
#include <optional>

#include <omm.hpp>

Expand All @@ -34,6 +35,8 @@ namespace omm
std::function<nvrhi::ShaderHandle(nvrhi::ShaderType type, const char* shaderName, const char* shaderEntryName)> shaders;
};

using MessageCallback = std::function<void(omm::MessageSeverity severity, const char* message)>;

enum class Operation
{
Invalid = 0,
Expand All @@ -48,6 +51,8 @@ namespace omm
nvrhi::TextureHandle alphaTexture;
uint32_t alphaTextureChannel = 3;
float alphaCutoff = 0.5f;
omm::OpacityState alphaCutoffGT = omm::OpacityState::Opaque;
omm::OpacityState alphaCutoffLE = omm::OpacityState::Transparent;
bool bilinearFilter = true;
bool enableLevelLineIntersection = true;
nvrhi::SamplerAddressMode sampleMode = nvrhi::SamplerAddressMode::Clamp;
Expand Down Expand Up @@ -126,7 +131,7 @@ namespace omm
uint32_t totalFullyUnknownTransparent = 0;
};

GpuBakeNvrhi(nvrhi::DeviceHandle device, nvrhi::CommandListHandle commandList, bool enableDebug, ShaderProvider* shaderProvider = nullptr);
GpuBakeNvrhi(nvrhi::DeviceHandle device, nvrhi::CommandListHandle commandList, bool enableDebug, ShaderProvider* shaderProvider = nullptr, std::optional<MessageCallback> callback = nullptr);
~GpuBakeNvrhi();

// CPU side pre-build info.
Expand Down
22 changes: 19 additions & 3 deletions omm-sdk/include/omm.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
#include <stddef.h>

#define OMM_VERSION_MAJOR 1
#define OMM_VERSION_MINOR 2
#define OMM_VERSION_MINOR 3
#define OMM_VERSION_BUILD 0

#define OMM_MAX_TRANSIENT_POOL_BUFFERS 8
Expand Down Expand Up @@ -378,8 +378,14 @@ typedef struct ommCpuBakeInputDesc
// Rejection threshold [0,1]. Unless OMMs achive a rate of at least rejectionThreshold known states OMMs will be discarded
// for the primitive. Use this to weed out "poor" OMMs.
float rejectionThreshold;
// The alpha cutoff value. texture > alphaCutoff ? Opaque : Transparent
// The alpha cutoff value. By default it's Texel Opacity = texture > alphaCutoff ? Opaque : Transparent
float alphaCutoff;
// alphaCutoffGT and alphaCutoffLE allows dynamic configuring of the alpha values in the texture in the following way:
// Texel opacity = texture > alphaCutoff ? alphaCutoffGT : alphaCutoffLE
// This can be used to construct different pairings such as transparent and unknown opaque which is useful
// for applications requiring partial accumulated opacity, like smoke and particle effects
ommOpacityState alphaCutoffLE;
ommOpacityState alphaCutoffGT;
// The global Format. May be overriden by the per-triangle subdivision level setting.
ommFormat format;
// Use Formats to control format on a per triangle granularity. If Format is set to Format::INVALID the global setting will
Expand Down Expand Up @@ -417,6 +423,8 @@ inline ommCpuBakeInputDesc ommCpuBakeInputDescDefault()
v.dynamicSubdivisionScale = 2;
v.rejectionThreshold = 0;
v.alphaCutoff = 0.5f;
v.alphaCutoffLE = ommOpacityState_Transparent;
v.alphaCutoffGT = ommOpacityState_Opaque;
v.format = ommFormat_OC1_4_State;
v.formats = NULL;
v.unknownStatePromotion = ommUnknownStatePromotion_ForceOpaque;
Expand Down Expand Up @@ -894,8 +902,14 @@ typedef struct ommGpuDispatchConfigDesc
uint32_t indexCount;
// If zero packed aligment is assumed.
uint32_t indexStrideInBytes;
// The alpha cutoff value. texture > alphaCutoff ? Opaque : Transparent.
// The alpha cutoff value. By default it's Texel Opacity = texture > alphaCutoff ? Opaque : Transparent
float alphaCutoff;
// alphaCutoffGT and alphaCutoffLE allows dynamic configuring of the alpha values in the texture in the following way:
// Texel opacity = texture > alphaCutoff ? alphaCutoffGT : alphaCutoffLE
// This can be used to construct different pairings such as transparent and unknown opaque which is useful
// for applications requiring partial accumulated opacity, like smoke and particle effects
ommOpacityState alphaCutoffLE;
ommOpacityState alphaCutoffGT;
// Configure the target resolution when running dynamic subdivision level. <= 0: disabled. > 0: The subdivision level be
// chosen such that a single micro-triangle covers approximatley a dynamicSubdivisionScale * dynamicSubdivisionScale texel
// area.
Expand Down Expand Up @@ -932,6 +946,8 @@ inline ommGpuDispatchConfigDesc ommGpuDispatchConfigDescDefault()
v.indexCount = 0;
v.indexStrideInBytes = 0;
v.alphaCutoff = 0.5f;
v.alphaCutoffLE = ommOpacityState_Transparent;
v.alphaCutoffGT = ommOpacityState_Opaque;
v.dynamicSubdivisionScale = 2;
v.globalFormat = ommFormat_OC1_4_State;
v.maxSubdivisionLevel = 8;
Expand Down
16 changes: 14 additions & 2 deletions omm-sdk/include/omm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,14 @@ namespace omm
// Rejection threshold [0,1]. Unless OMMs achive a rate of at least rejectionThreshold known states OMMs will be discarded
// for the primitive. Use this to weed out "poor" OMMs.
float rejectionThreshold = 0;
// The alpha cutoff value. texture > alphaCutoff ? Opaque : Transparent
// The alpha cutoff value. By default it's Texel Opacity = texture > alphaCutoff ? Opaque : Transparent
float alphaCutoff = 0.5f;
// alphaCutoffGT and alphaCutoffLE allows dynamic configuring of the alpha values in the texture in the following way:
// Texel opacity = texture > alphaCutoff ? alphaCutoffGT : alphaCutoffLE
// This can be used to construct different pairings such as transparent and unknown opaque which is useful
// for applications requiring partial accumulated opacity, like smoke and particle effects
omm::OpacityState alphaCutoffLE = omm::OpacityState::Transparent;
omm::OpacityState alphaCutoffGT = omm::OpacityState::Opaque;
// The global Format. May be overriden by the per-triangle subdivision level setting.
Format format = Format::OC1_4_State;
// Use Formats to control format on a per triangle granularity. If Format is set to Format::INVALID the global setting will
Expand Down Expand Up @@ -743,8 +749,14 @@ namespace omm
uint32_t indexCount = 0;
// If zero packed aligment is assumed.
uint32_t indexStrideInBytes = 0;
// The alpha cutoff value. texture > alphaCutoff ? Opaque : Transparent.
// The alpha cutoff value. By default it's Texel Opacity = texture > alphaCutoff ? Opaque : Transparent
float alphaCutoff = 0.5f;
// alphaCutoffGT and alphaCutoffLE allows dynamic configuring of the alpha values in the texture in the following way:
// Texel Opacity = texture > alphaCutoff ? alphaCutoffGT : alphaCutoffLE
// This can be used to construct different pairings such as transparent and unknown opaque which is useful
// for applications requiring partial accumulated opacity, like smoke and particle effects
omm::OpacityState alphaCutoffLE = omm::OpacityState::Transparent;
omm::OpacityState alphaCutoffGT = omm::OpacityState::Opaque;
// Configure the target resolution when running dynamic subdivision level. <= 0: disabled. > 0: The subdivision level be
// chosen such that a single micro-triangle covers approximatley a dynamicSubdivisionScale * dynamicSubdivisionScale texel
// area.
Expand Down
45 changes: 30 additions & 15 deletions omm-sdk/shaders/omm.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -46,29 +46,44 @@ enum class TexCoordFormat : int {
MAX_NUM
};

OpacityState _getOpacityStateInternal(uint numOpaque, uint numTransparent)
bool IsKnown(OpacityState state)
{
if (numOpaque == 0)
return ((uint) state & 1u) == (uint) state;
}

bool IsUnknown(OpacityState state)
{
return !IsKnown(state);
}

OpacityState GetUnknownVersionOf(OpacityState state)
{
return (OpacityState)((uint)state | 2u);
}

OpacityState _getOpacityStateInternal(uint numAboveAlpha, uint numBelowAlpha, OpacityState alphaCutoffGT, OpacityState alphaCutoffLE)
{
if (numAboveAlpha == 0)
{
return OpacityState::Transparent;
}
else if (numTransparent == 0)
return alphaCutoffLE;
}
else if (numBelowAlpha == 0)
{
return OpacityState::Opaque;
}
else if (numTransparent > numOpaque)
return alphaCutoffGT;
}
else if (numBelowAlpha > numAboveAlpha)
{
return OpacityState::UnknownTransparent;
}
else // if (numTransparent <= numOpaque)
return GetUnknownVersionOf(alphaCutoffLE);
}
else // if (numBelowAlpha <= numAboveAlpha)
{
return OpacityState::UnknownOpaque;
}
return GetUnknownVersionOf(alphaCutoffGT);
}
}

OpacityState GetOpacityState(uint numOpaque, uint numTransparent, OMMFormat ommFormat)
OpacityState GetOpacityState(uint numAboveAlpha, uint numBelowAlpha, uint /*OpacityState*/ alphaCutoffGT, uint /*OpacityState*/ alphaCutoffLE, OMMFormat ommFormat)
{
OpacityState opacityState = _getOpacityStateInternal(numOpaque, numTransparent);
OpacityState opacityState = _getOpacityStateInternal(numAboveAlpha, numBelowAlpha, (OpacityState) alphaCutoffGT, (OpacityState) alphaCutoffLE);
if (ommFormat == OMMFormat::OC1_2)
return (OpacityState)((uint)opacityState & 1u);
return opacityState;
Expand Down
4 changes: 2 additions & 2 deletions omm-sdk/shaders/omm_compress.cs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void main(uint3 tid : SV_DispatchThreadID)
const uint2 counts = OMM_SUBRESOURCE_LOAD2(BakeResultBuffer, vmBakeResultOffset);
OMM_SUBRESOURCE_STORE2(BakeResultBuffer, vmBakeResultOffset, 0); // clear for next iteration

OpacityState opacityState = GetOpacityState(/*numOpaque*/ counts.x, /*numTransparent*/ counts.y, vmFormat);
OpacityState opacityState = GetOpacityState(/*numOpaque*/ counts.x, /*numTransparent*/ counts.y, g_GlobalConstants.AlphaCutoffGT, g_GlobalConstants.AlphaCutoffLE, vmFormat);

if (microTriangleIndex < numMicroTrianglesPerPrimitive)
StoreMacroTriangleState(opacityState, vmPrimitiveIndex);
Expand Down Expand Up @@ -132,7 +132,7 @@ void main(uint3 tid : SV_DispatchThreadID)
const uint2 counts = OMM_SUBRESOURCE_LOAD2(BakeResultBuffer, vmBakeResultOffset);
OMM_SUBRESOURCE_STORE2(BakeResultBuffer, vmBakeResultOffset, 0); // clear for next iteration

OpacityState opacityState = GetOpacityState(/*numOpaque*/ counts.x, /*numTransparent*/ counts.y, vmFormat);
OpacityState opacityState = GetOpacityState(/*numOpaque*/ counts.x, /*numTransparent*/ counts.y, g_GlobalConstants.AlphaCutoffGT, g_GlobalConstants.AlphaCutoffLE, vmFormat);

if (microTriangleIndex < numMicroTrianglesPerPrimitive)
StoreMacroTriangleState(opacityState, vmPrimitiveIndex);
Expand Down
6 changes: 3 additions & 3 deletions omm-sdk/shaders/omm_global_cb.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ OMM_CONSTANTS_START(GlobalConstants) \
OMM_CONSTANT(uint, TexCoord1Stride) \
\
OMM_CONSTANT(float, AlphaCutoff) \
OMM_CONSTANT(uint, AlphaCutoffLE) \
OMM_CONSTANT(uint, AlphaCutoffGT) \
OMM_CONSTANT(uint, AlphaTextureChannel) \
\
OMM_CONSTANT(uint, FilterType) /* TextureFilterMode */ \
OMM_CONSTANT(uint, EnableLevelLine) \
\
OMM_CONSTANT(uint, EnablePostDispatchInfoStats) \
OMM_CONSTANT(uint, IndirectDispatchEntryStride) \
OMM_CONSTANT(uint, Pad1) \
OMM_CONSTANT(uint, Pad2) \
\
OMM_CONSTANT(float2, TexSize) \
OMM_CONSTANT(float2, InvTexSize) \
Expand Down
5 changes: 2 additions & 3 deletions omm-sdk/shaders/omm_rasterize.vs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,10 @@ void main(
const float4 color = t_alphaTexture.SampleLevel(s_samplers[g_GlobalConstants.SamplerIndex], texCoord.xy, 0);
const float alpha = color[g_GlobalConstants.AlphaTextureChannel];

const uint isOpaque = g_GlobalConstants.AlphaCutoff < alpha;
const OpacityState vmState = GetOpacityState(isOpaque, !isOpaque, OMMFormat::OC1_4);
const OpacityState vertexState = (OpacityState) (g_GlobalConstants.AlphaCutoff < alpha ? (uint) OpacityState::Opaque : (uint) OpacityState::Transparent);

o_primitiveIndex = i_primitiveIndex;
o_texCoord = texCoord;
o_vmStateAtVertex = (uint)vmState;
o_vmStateAtVertex = (uint)vertexState;
o_posClip = raster::TexCoord_to_VS_SV_Position(texCoord);
}
2 changes: 1 addition & 1 deletion omm-sdk/shaders/omm_rasterize_cs.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ void main(uint3 tid : SV_DispatchThreadID)
}
}

const OpacityState opacityState = GetOpacityState(isOpaque, isTransparent, ommFormat);
const OpacityState opacityState = GetOpacityState(isOpaque, isTransparent, g_GlobalConstants.AlphaCutoffGT, g_GlobalConstants.AlphaCutoffLE, ommFormat);

StoreMacroTriangleState(opacityState, vmPrimitiveIndex);

Expand Down
2 changes: 1 addition & 1 deletion omm-sdk/shaders/omm_rasterize_debug.ps.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void main(

const uint numOpaque = OMM_SUBRESOURCE_LOAD(BakeResultBuffer, microTriOffset);
const uint numTrans = OMM_SUBRESOURCE_LOAD(BakeResultBuffer, microTriOffset + 4);
const OpacityState state = GetOpacityState(numOpaque, numTrans, OMMFormat::OC1_4);
const OpacityState state = GetOpacityState(numOpaque, numTrans, g_GlobalConstants.AlphaCutoffGT, g_GlobalConstants.AlphaCutoffLE, OMMFormat::OC1_4);
const float3 debugColor = GetDebugColorForState(state);

const float2 texCoord = raster::PS_SV_Position_to_TexCoord(i_svPosition);
Expand Down
Loading

0 comments on commit 01fdb76

Please sign in to comment.