Getting pretty good results on full res gpu renders since removing block to scale by sample rate

This commit is contained in:
Alex Wysoczanski 2026-03-25 22:48:14 -04:00
parent f9795ce17d
commit cb828d2357
5 changed files with 59 additions and 42 deletions

View file

@ -5,7 +5,8 @@
# .\compare-skipmip.ps1 -Scene "path\to\scene.pbrt" -Spp 16
# .\compare-skipmip.ps1 "scene.pbrt" 16
# .\compare-skipmip.ps1 "scene.pbrt" 16 -ShowProgress --gpu
# Omit -Spp to use Integrator "integer pixelsamples" from the .pbrt file (same as pbrt.exe without --spp).
# .\compare-skipmip.ps1 "scene.pbrt" -ShowProgress --gpu (--gpu is not parsed as Spp; use -Gpu or trailing --gpu)
# Omit -Spp and any leading digits-only tail so pbrt.exe does not get --spp (scene Integrator "integer pixelsamples" applies).
#
# Render progress: stdout is written to the .txt log live while pbrt runs (poll ~8 Hz for console echo).
# Optional -ExtraPbrtArgs is appended for both runs (e.g. --wavefront).
@ -19,8 +20,10 @@ param(
[Parameter(Mandatory = $true, Position = 0)]
[string] $Scene,
[Parameter(Mandatory = $false, Position = 1)]
[int] $Spp = 0,
# Named only (no Position): so trailing tokens like --gpu go to RemainingArguments, not here.
# Optional positional spp: first RemainingArguments token that is all-digits (>= 1) when -Spp omitted.
[Parameter(Mandatory = $false)]
$Spp = $null,
[string] $PbrtExe = "",
[string] $LogDir = "",
@ -295,32 +298,59 @@ $logNoMip = Join-Path $LogDir ("{0}-{1}-nomip.txt" -f $base, $stamp)
$logSkipMip = Join-Path $LogDir ("{0}-{1}-skipmip.txt" -f $base, $stamp)
$summaryPath = Join-Path $LogDir ("{0}-{1}-comparison.txt" -f $base, $stamp)
$sppForCli = $null
$sppFromNamed = $false
if ($PSBoundParameters.ContainsKey('Spp')) {
if ($Spp -lt 1) {
$sppFromNamed = $true
if ($null -eq $Spp -or "$Spp" -eq '') {
throw "Spp was specified but is empty; omit -Spp to use the scene file default."
}
try {
$sppForCli = [int]$Spp
} catch {
throw "Invalid Spp value (expected positive integer): $Spp"
}
if ($sppForCli -lt 1) {
throw "Spp must be >= 1 when specified (omit -Spp to use the scene file default)."
}
}
$tailPbrt = New-Object System.Collections.Generic.List[string]
if ($RemainingArguments) {
foreach ($a in $RemainingArguments) {
$tailPbrt.Add($a)
}
}
if (-not $sppFromNamed -and $tailPbrt.Count -gt 0) {
$head = $tailPbrt[0]
if ($head -match '^\d+$') {
$trySpp = [int]$head
if ($trySpp -ge 1) {
$sppForCli = $trySpp
$tailPbrt.RemoveAt(0)
}
}
}
$common = @(
$sceneFull,
"--stats"
)
if ($PSBoundParameters.ContainsKey('Spp')) {
$common += @("--spp", "$Spp")
if ($null -ne $sppForCli) {
$common += @("--spp", "$sppForCli")
}
$common += $ExtraPbrtArgs
$gpuWanted = [bool]$Gpu
$tailPbrt = New-Object System.Collections.Generic.List[string]
if ($RemainingArguments) {
foreach ($a in $RemainingArguments) {
if ($a -eq '--gpu') {
$gpuWanted = $true
} else {
$tailPbrt.Add($a)
}
$finalTail = New-Object System.Collections.Generic.List[string]
foreach ($a in $tailPbrt) {
if ($a -eq '--gpu') {
$gpuWanted = $true
} else {
$finalTail.Add($a)
}
}
$tailPbrt = $finalTail
if ($gpuWanted -and ($common -notcontains '--gpu')) {
$common += '--gpu'
}
@ -328,7 +358,7 @@ if ($tailPbrt.Count -gt 0) {
$common += [string[]]$tailPbrt.ToArray()
}
$sppLabel = if ($PSBoundParameters.ContainsKey('Spp')) { "$Spp" } else { "(scene file default)" }
$sppLabel = if ($null -ne $sppForCli) { "$sppForCli" } else { "(scene file default)" }
Write-Host "=== pbrt compare-skipmip ===" -ForegroundColor Cyan
Write-Host "pbrt: $PbrtExe"

View file

@ -33,7 +33,7 @@ void RenderCPU(BasicScene &parsedScene) {
Sampler sampler = parsedScene.GetSampler();
LOG_VERBOSE("Image texture mip preprocess");
RunImageTextureMipPreprocess(parsedScene, camera, sampler.SamplesPerPixel());
RunImageTextureMipPreprocess(parsedScene, camera);
// Textures
LOG_VERBOSE("Starting textures");

View file

@ -399,8 +399,7 @@ static bool AffineTripleScalarGradients2D(Float x0, Float y0, Float x1, Float y1
return true;
}
static Float MinPrimaryContinuousLodForUse(const Camera &camera, int samplesPerPixel,
const ImageTextureGeometryUse &use,
static Float MinPrimaryContinuousLodForUse(const Camera &camera, const ImageTextureGeometryUse &use,
int pyramidLevels, Allocator alloc) {
(void)alloc;
if (!Options || Options->disableTextureFiltering || !use.localTriangles ||
@ -422,10 +421,6 @@ static Float MinPrimaryContinuousLodForUse(const Camera &camera, int samplesPerP
const Transform &worldFromShape = use.worldFromShape;
Bounds2i pb = proj->GetFilm().PixelBounds();
Float sppScale = 1.f;
if (!Options->disablePixelJitter)
sppScale = std::max<Float>(0.125f, 1.f / std::sqrt(Float(samplesPerPixel)));
constexpr Float kMinW = 1e-6f;
auto lodForTriangle = [&](const ImageTextureMeshTriangle &tri) -> Float {
@ -484,11 +479,6 @@ static Float MinPrimaryContinuousLodForUse(const Camera &camera, int samplesPerP
Float dudy = (dUow_dy - u * dIw_dy) / inv_w;
Float dvdy = (dVow_dy - v * dIw_dy) / inv_w;
dudx *= sppScale;
dvdx *= sppScale;
dudy *= sppScale;
dvdy *= sppScale;
if (!IsFinite(dudx) || !IsFinite(dvdx) || !IsFinite(dudy) || !IsFinite(dvdy))
return Infinity;
@ -532,9 +522,8 @@ static Float MinPrimaryContinuousLodForUse(const Camera &camera, int samplesPerP
}
int ComputeImageTextureSafeDownsizesFromPreprocess(
const Camera &camera, int samplesPerPixel,
const std::vector<ImageTextureGeometryUse> &usesForTexture, int mipmapPyramidLevels,
Allocator alloc) {
const Camera &camera, const std::vector<ImageTextureGeometryUse> &usesForTexture,
int mipmapPyramidLevels, Allocator alloc) {
if (usesForTexture.empty())
return 0;
@ -562,8 +551,8 @@ int ComputeImageTextureSafeDownsizesFromPreprocess(
size_t i = (size_t)ui;
if (bailForZeroPairSafe.load(std::memory_order_relaxed))
return;
Float minLod = MinPrimaryContinuousLodForUse(
camera, samplesPerPixel, usesForTexture[i], mipmapPyramidLevels, alloc);
Float minLod =
MinPrimaryContinuousLodForUse(camera, usesForTexture[i], mipmapPyramidLevels, alloc);
minLods[i] = minLod;
lodComputed[i] = 1;
if (pairSafeFromMinLod(minLod) == 0)
@ -610,8 +599,7 @@ int ComputeImageTextureSafeDownsizesFromPreprocess(
return std::max(0, textureMinSafeDownsizes);
}
void RunImageTextureMipPreprocess(BasicScene &scene, const Camera &camera,
int samplesPerPixel) {
void RunImageTextureMipPreprocess(BasicScene &scene, const Camera &camera) {
ClearImageTextureMipDownsizeOverrides();
if (!Options || !Options->skipMipImageTextures)
return;
@ -654,8 +642,8 @@ void RunImageTextureMipPreprocess(BasicScene &scene, const Camera &camera,
" (no trianglemesh/plymesh reflectance imagemap uses found; safe downsizes 0)\n");
}
} else {
safeDownsizes = ComputeImageTextureSafeDownsizesFromPreprocess(
camera, samplesPerPixel, uses, pyramidLevels, alloc);
safeDownsizes =
ComputeImageTextureSafeDownsizesFromPreprocess(camera, uses, pyramidLevels, alloc);
}
if (MipPreprocessLogDetail())

View file

@ -45,15 +45,14 @@ struct ImageTextureGeometryUse {
// perspective/orthographic; spherical/realistic cameras yield 0 safe downsizes). UV imagemap
// on reflectance for diffuse / coateddiffuse / diffusetransmission and mix thereof;
// trianglemesh + plymesh; includes ObjectInstance placements (transformed into render space).
// Independent of integrator samples per pixel (screen-to-texture footprint uses the pixel grid).
int ComputeImageTextureSafeDownsizesFromPreprocess(
const Camera &camera, int samplesPerPixel,
const std::vector<ImageTextureGeometryUse> &usesForTexture, int mipmapPyramidLevels,
Allocator alloc);
const Camera &camera, const std::vector<ImageTextureGeometryUse> &usesForTexture,
int mipmapPyramidLevels, Allocator alloc);
// Clears prior overrides, then assigns per-file safe downsizes before image loads.
// No-op when --skipmip is off (aside from clearing stale overrides).
void RunImageTextureMipPreprocess(BasicScene &scene, const Camera &camera,
int samplesPerPixel);
void RunImageTextureMipPreprocess(BasicScene &scene, const Camera &camera);
} // namespace pbrt

View file

@ -115,7 +115,7 @@ WavefrontPathIntegrator::WavefrontPathIntegrator(
sampler = scene.GetSampler();
LOG_VERBOSE("Image texture mip preprocess");
RunImageTextureMipPreprocess(scene, camera, sampler.SamplesPerPixel());
RunImageTextureMipPreprocess(scene, camera);
// Textures
LOG_VERBOSE("Starting to create textures");