Skip to content

Comments

Autoexposure example restoration#137

Open
devshgraphicsprogramming wants to merge 97 commits intomasterfrom
autoexposure_ex
Open

Autoexposure example restoration#137
devshgraphicsprogramming wants to merge 97 commits intomasterfrom
autoexposure_ex

Conversation

@devshgraphicsprogramming
Copy link
Member

No description provided.

nipunG314 and others added 28 commits July 19, 2024 22:07
Comment on lines 12 to 17
float meteringWindowScaleX, meteringWindowScaleY;
float meteringWindowOffsetX, meteringWindowOffsetY;
float lumaMin, lumaMax;
uint32_t sampleCountX, sampleCountY;
uint32_t viewportSizeX, viewportSizeY;
uint64_t lumaMeterBDA;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should pack these up intro structs in nbl::hlsl::luma_meter and friends

P.S. I see you already have, why not use things like nbl::hlsl::luma_meter::LumaMeteringWindow directly here?

Comment on lines 788 to 791
const uint32_t2 dispatchSize = {
1 + ((gpuImgExtent.width / 2) - 1) / SubgroupSize,
1 + ((gpuImgExtent.height / 2) - 1) / SubgroupSize
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Half dispatch with full viewport UV means you sample only the top left quarter, EV is computed from that quarter and then applied to the whole image so exposure drifts when luminance is not uniform

uint32_t texWidth, texHeight;
texture.GetDimensions(texWidth, texHeight);
meter.sampleLuma(pushData.window, val_accessor, tex, sdata, (float32_t2)(glsl::gl_WorkGroupID() * glsl::gl_WorkGroupSize()), float32_t2(texWidth, texHeight));

https://github.com/Devsh-Graphics-Programming/Nabla/blob/8466a9db6ee2d060abccb5710461f3f2d97ecf5a/include/nbl/builtin/hlsl/luma_meter/geom_mean.hlsl#L105

counterexample https://godbolt.org/z/de41xd9ro

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved

inline void workLoopBody() override
{
memset(m_gatherMemory, 0, m_gatherBuffer->getSize());
memset(m_histoMemory, 0, m_gatherBuffer->getSize());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This typo keeps most bins dirty and EV is biased, use m_histoBuffer->getSize()

counterexample https://godbolt.org/z/Mozo84eYY

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved

tonemapper::Reinhard<float32_t> reinhard = tonemapper::Reinhard<float32_t>::create(EV, 0.18f, 0.85f);
float32_t3 tonemappedColor = mul(colorspace::decode::XYZtoscRGB, reinhard(CIEColor));

textureOut[pos] = float32_t4(colorspace::oetf::sRGB(tonemappedColor), 1.0f);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No bounds guard and we have OOB write. We go 1280x720 and dispatch is ceil(Dimensions/SubgroupSize). With SubgroupSize 32 it is 1280x736 coverage

constexpr static inline uint32_t2 Dimensions = { 1280, 720 };

const uint32_t2 dispatchSize = {
1 + ((Dimensions.x) - 1) / SubgroupSize,
1 + ((Dimensions.y) - 1) / SubgroupSize
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about it, could you please confirm the expected metering region is $uv\in[0.1,0.9]^2$? If so then with current inputs

and flow like

we have

  • dispatchSize=(16,9)
  • windowScale=(0.8/(16*32),0.8/(9*32))=(0.0015625,0.002777...)
  • (tileOffset+coord) spans [0,511]x[0,287]

and then sampled UV is approximately

  • $uv_x\in[0.100000,0.100624]$
  • $uv_y\in[0.100000,0.101107]$

this is a tiny rectangle near (0.1,0.1) not the intended (I guess) metering window because the coordinates are effectively normalized twice, first by viewportSize in shiftedCoord = (tileOffset + coord) / viewportSize and then scaled again by windowScale = meteringUVRange / (dispatchSize * SubgroupSize).

https://github.com/Devsh-Graphics-Programming/Nabla/blob/79fad2f7d16ba75347c94a8b4327042b4d786547/include/nbl/builtin/hlsl/luma_meter/geom_mean.hlsl#L126

pc.window = luma_meter::MeteringWindow::create(meteringUVRange / (float32_t2(dispatchSize) * float(SubgroupSize)), MeteringMinUV);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved

tonemapper::Reinhard<float32_t> reinhard = tonemapper::Reinhard<float32_t>::create(EV, 0.18, 0.85f);
float32_t3 tonemappedColor = mul(colorspace::decode::XYZtoscRGB, reinhard(CIEColor));

textureOut[pos] = float32_t4(colorspace::oetf::sRGB(tonemappedColor), 1.0f);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same OOB issue as in #137 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants