Dither paths, render hook deinit, undef Success.

This commit is contained in:
Dario 2024-04-30 21:17:40 -03:00
parent abb1b4c01e
commit 92cf3845a0
21 changed files with 154 additions and 14 deletions

View File

@ -1207,6 +1207,9 @@ namespace RT64 {
const uint32_t textDetail = callDesc.otherMode.textDetail();
const uint32_t textFilt = callDesc.otherMode.textFilt();
const uint32_t textLut = callDesc.otherMode.textLUT();
const uint32_t alphaDither = callDesc.otherMode.alphaDither();
const uint32_t rgbDither = callDesc.otherMode.rgbDither();
ImGui::Indent();
ImGui::Text("Cycle type:");
@ -1280,6 +1283,46 @@ namespace RT64 {
break;
}
ImGui::Text("Alpha Dither:");
ImGui::SameLine();
switch (alphaDither) {
case G_AD_PATTERN:
ImGui::Text("G_AD_PATTERN");
break;
case G_AD_NOTPATTERN:
ImGui::Text("G_AD_NOTPATTERN");
break;
case G_AD_NOISE:
ImGui::Text("G_AD_NOISE");
break;
case G_AD_DISABLE:
ImGui::Text("G_AD_DISABLE");
break;
default:
ImGui::Text("Unknown");
break;
}
ImGui::Text("RGB Dither:");
ImGui::SameLine();
switch (rgbDither) {
case G_CD_MAGICSQ:
ImGui::Text("G_CD_MAGICSQ");
break;
case G_CD_BAYER:
ImGui::Text("G_CD_BAYER");
break;
case G_CD_NOISE:
ImGui::Text("G_CD_NOISE");
break;
case G_CD_DISABLE:
ImGui::Text("G_CD_DISABLE");
break;
default:
ImGui::Text("Unknown");
break;
}
ImGui::Text("Combiner key: %s", (callDesc.otherMode.combKey() == G_CK_KEY) ? "G_CK_KEY" : "G_CK_NONE");
ImGui::Text("Texture LOD: %s", (callDesc.otherMode.textLOD() == G_TL_LOD) ? "G_TL_LOD" : "G_TL_TILE");
ImGui::Text("Texture perspective: %s", (callDesc.otherMode.textPersp() == G_TP_PERSP) ? "G_TP_PERSP" : "G_TP_NONE");

View File

@ -162,9 +162,9 @@ namespace RT64 {
return SetupResult::GraphicsDeviceNotFound;
}
// Call the init hook if one was attached
RenderHookInit* initHook = GetRenderHookInit();
if (initHook) {
// Call the init hook if one was attached.
RenderHookInit *initHook = GetRenderHookInit();
if (initHook != nullptr) {
initHook(renderInterface.get(), device.get());
}
@ -463,6 +463,13 @@ namespace RT64 {
state.reset();
workloadQueue.reset();
presentQueue.reset();
// Call the deinit hook if one was attached.
RenderHookDeinit *deinitHook = GetRenderHookDeinit();
if (deinitHook != nullptr) {
deinitHook();
}
drawDataUploader.reset();
transformsUploader.reset();
tilesUploader.reset();

View File

@ -35,6 +35,8 @@
# include "script/rt64_script.h"
#endif
#undef Success
namespace RT64 {
struct ApplicationConfiguration {
std::filesystem::path appId = "rt64";

View File

@ -36,6 +36,7 @@ namespace RT64 {
modifiedBytes = 0;
RAMBytes = 0;
RAMHash = 0;
ditherPatterns.fill(0);
lastWriteType = Type::None;
lastWriteFmt = 0;
lastWriteTimestamp = 0;
@ -123,13 +124,13 @@ namespace RT64 {
}
}
void Framebuffer::copyRenderTargetToNative(RenderWorker *worker, RenderTarget *target, uint32_t dstRowWidth, uint32_t dstRowStart, uint32_t dstRowEnd, uint8_t fmt, const ShaderLibrary *shaderLibrary) {
void Framebuffer::copyRenderTargetToNative(RenderWorker *worker, RenderTarget *target, uint32_t dstRowWidth, uint32_t dstRowStart, uint32_t dstRowEnd, uint8_t fmt, uint32_t ditherRandomSeed, const ShaderLibrary *shaderLibrary) {
assert(worker != nullptr);
assert(target != nullptr);
assert(dstRowStart < height);
assert(dstRowEnd <= height);
nativeTarget.copyToNative(worker, target, dstRowWidth, dstRowStart, dstRowEnd, siz, fmt, shaderLibrary);
nativeTarget.copyToNative(worker, target, dstRowWidth, dstRowStart, dstRowEnd, siz, fmt, bestDitherPattern(), ditherRandomSeed, shaderLibrary);
}
void Framebuffer::copyNativeToRAM(uint8_t *dst, uint32_t dstRowWidth, uint32_t dstRowStart, uint32_t dstRowEnd) {
@ -177,4 +178,14 @@ namespace RT64 {
sizChanged = false;
rdramChanged = false;
}
void Framebuffer::addDitherPatterns(const std::array<uint32_t, 4> &extraPatterns) {
for (uint32_t i = 0; i < ditherPatterns.size(); i++) {
ditherPatterns[i] += extraPatterns[i];
}
}
uint32_t Framebuffer::bestDitherPattern() const {
return std::max_element(ditherPatterns.begin(), ditherPatterns.end()) - ditherPatterns.begin();
}
};

View File

@ -4,6 +4,7 @@
#pragma once
#include <array>
#include <stdint.h>
#include "render/rt64_native_target.h"
@ -37,6 +38,7 @@ namespace RT64 {
uint32_t modifiedBytes;
uint32_t RAMBytes;
uint64_t RAMHash;
std::array<uint32_t, 4> ditherPatterns;
bool widthChanged;
bool sizChanged;
bool rdramChanged;
@ -55,9 +57,11 @@ namespace RT64 {
FramebufferChange *readChangeFromStorage(RenderWorker *worker, const FramebufferStorage &fbStorage, FramebufferChangePool &fbChangePool, Type type, uint8_t fmt,
uint32_t maxFbPairIndex, uint32_t rowStart, uint32_t rowCount, const ShaderLibrary *shaderLibrary);
void copyRenderTargetToNative(RenderWorker *worker, RenderTarget *target, uint32_t dstRowWidth, uint32_t dstRowStart, uint32_t dstRowEnd, uint8_t fmt, const ShaderLibrary *shaderLibrary);
void copyRenderTargetToNative(RenderWorker *worker, RenderTarget *target, uint32_t dstRowWidth, uint32_t dstRowStart, uint32_t dstRowEnd, uint8_t fmt, uint32_t ditherRandomSeed, const ShaderLibrary *shaderLibrary);
void copyNativeToRAM(uint8_t *dst, uint32_t dstRowWidth, uint32_t dstRowStart, uint32_t dstRowEnd);
void clearChanged();
void addDitherPatterns(const std::array<uint32_t, 4> &extraPatterns);
uint32_t bestDitherPattern() const;
};
struct FramebufferTile {
@ -69,6 +73,7 @@ namespace RT64 {
uint32_t right;
uint32_t bottom;
uint32_t lineWidth;
uint32_t ditherPattern;
bool valid() const {
return (bottom > top) && (right > left);

View File

@ -123,6 +123,8 @@ namespace RT64 {
tileCopy.ulScaleS = true;
tileCopy.texelShift = { 0, 0 };
tileCopy.texelMask = { UINT_MAX, UINT_MAX };
tileCopy.ditherOffset = { tileCopy.left, tileCopy.top };
tileCopy.ditherPattern = op.createTileCopy.fbTile.ditherPattern;
tileCopy.readColorFromStorage = false;
tileCopy.readDepthFromStorage = false;
tileCopy.ignore = false;
@ -275,6 +277,8 @@ namespace RT64 {
dstTile.usedWidth = dstTileWidth;
dstTile.usedHeight = dstTileHeight;
dstTile.sampleScale = sampleScale;
dstTile.ditherOffset = srcTile.ditherOffset;
dstTile.ditherPattern = srcTile.ditherPattern;
srcTile.ignore = false;
const bool insufficientSize = (dstTile.textureWidth < dstTileWidth) || (dstTile.textureHeight < dstTileHeight);
@ -318,6 +322,9 @@ namespace RT64 {
c.dstSiz = op.reinterpretTile.dstSiz;
c.dstFmt = op.reinterpretTile.dstFmt;
c.tlutFormat = (op.reinterpretTile.tlutHash != 0) ? (op.reinterpretTile.tlutFormat + 1) : 0;
c.ditherOffset = dstTile.ditherOffset;
c.ditherPattern = dstTile.ditherPattern;
c.ditherRandomSeed = uint32_t(writeTimestamp) + op.reinterpretTile.dstId;
dispatch.srcTexture = srcTile.texture.get();
dispatch.dstTexture = dstTile.texture.get();
@ -460,6 +467,7 @@ namespace RT64 {
outTile.address = fb->addressStart;
outTile.siz = fb->siz;
outTile.fmt = fb->lastWriteFmt;
outTile.ditherPattern = fb->bestDitherPattern();
return true;
}
@ -828,6 +836,7 @@ namespace RT64 {
auto it = framebuffers.begin();
while (it != framebuffers.end()) {
it->second.maxHeight = 0;
it->second.ditherPatterns.fill(0);
it++;
}
}

View File

@ -89,6 +89,8 @@ namespace RT64 {
bool ulScaleT = true;
interop::uint2 texelShift = { 0, 0 };
interop::uint2 texelMask = { UINT_MAX, UINT_MAX };
interop::uint2 ditherOffset = { 0, 0 };
uint32_t ditherPattern = 0;
float sampleScale = 1.0f;
bool readColorFromStorage = false;
bool readDepthFromStorage = false;

View File

@ -19,6 +19,7 @@ namespace RT64 {
depthRead = false;
depthWrite = false;
syncRequired = false;
ditherPatterns.fill(0);
scissorRect.reset();
startFbDiscards.clear();
startFbOperations.clear();
@ -34,6 +35,10 @@ namespace RT64 {
depthRead = depthRead || gameCall.callDesc.otherMode.zCmp();
depthWrite = depthWrite || gameCall.callDesc.otherMode.zUpd();
gameCallCount++;
// Track what type of color dither this call used.
uint32_t ditherIndex = (gameCall.callDesc.otherMode.rgbDither() >> G_MDSFT_RGBDITHER) & 0x3;
ditherPatterns[ditherIndex]++;
}
bool FramebufferPair::inProjection(uint32_t transformsIndex, Projection::Type type) const {

View File

@ -43,6 +43,7 @@ namespace RT64 {
std::vector<uint32_t> startFbDiscards;
std::vector<FramebufferOperation> startFbOperations;
std::vector<FramebufferOperation> endFbOperations;
std::array<uint32_t, 4> ditherPatterns;
FixedRect scissorRect;
FixedRect drawColorRect;
FixedRect drawDepthRect;

View File

@ -466,6 +466,7 @@ namespace RT64 {
RT64::Framebuffer *colorFb = &framebufferManager.get(colorImg.address, colorImg.siz, colorImg.width, colorHeight);
colorImg.formatChanged = colorFb->widthChanged || colorFb->sizChanged || colorFb->rdramChanged;
colorFb->clearChanged();
colorFb->addDitherPatterns(fbPair.ditherPatterns);
RT64::Framebuffer *depthFb = nullptr;
if (fbPair.depthRead || fbPair.depthWrite) {
@ -1383,10 +1384,10 @@ namespace RT64 {
}
// Copy results from render targets back to RAM.
colorFb->copyRenderTargetToNative(ext.framebufferGraphicsWorker, colorTarget, colorWriteWidth, colorRowStart, colorRowEnd, colorImg.fmt, ext.shaderLibrary);
colorFb->copyRenderTargetToNative(ext.framebufferGraphicsWorker, colorTarget, colorWriteWidth, colorRowStart, colorRowEnd, colorImg.fmt, ditherRandomSeed++, ext.shaderLibrary);
if (depthWriteWidth > 0) {
depthFb->copyRenderTargetToNative(ext.framebufferGraphicsWorker, depthTarget, depthWriteWidth, depthRowStart, depthRowEnd, G_IM_FMT_DEPTH, ext.shaderLibrary);
depthFb->copyRenderTargetToNative(ext.framebufferGraphicsWorker, depthTarget, depthWriteWidth, depthRowStart, depthRowEnd, G_IM_FMT_DEPTH, ditherRandomSeed++, ext.shaderLibrary);
}
}

View File

@ -117,6 +117,7 @@ namespace RT64 {
bool configurationSaveQueued = false;
uint64_t workloadId = 0;
uint64_t presentId = 0;
uint32_t ditherRandomSeed = 0;
External ext;
struct Extended {

View File

@ -159,6 +159,8 @@ namespace RT64 {
nativeCB.resolution = { width, height };
nativeCB.fmt = fmt;
nativeCB.siz = siz;
nativeCB.ditherPattern = 0;
nativeCB.ditherRandomSeed = 0;
// Assert for formats that have not been implemented yet because hardware verification is pending.
assert((nativeCB.siz != G_IM_SIZ_4b) && "Unimplemented 4 bits Readback mode.");
@ -228,7 +230,7 @@ namespace RT64 {
return modifiedCount;
}
void NativeTarget::copyToNative(RenderWorker *worker, RenderTarget *srcTarget, uint32_t rowWidth, uint32_t rowStart, uint32_t rowEnd, uint8_t siz, uint8_t fmt, const ShaderLibrary *shaderLibrary) {
void NativeTarget::copyToNative(RenderWorker *worker, RenderTarget *srcTarget, uint32_t rowWidth, uint32_t rowStart, uint32_t rowEnd, uint8_t siz, uint8_t fmt, uint32_t ditherPattern, uint32_t ditherRandomSeed, const ShaderLibrary *shaderLibrary) {
assert(worker != nullptr);
srcTarget->resolveTarget(worker);
@ -243,6 +245,8 @@ namespace RT64 {
nativeCB.resolution = { rowWidth, rowEnd - rowStart };
nativeCB.fmt = fmt;
nativeCB.siz = siz;
nativeCB.ditherPattern = ditherPattern;
nativeCB.ditherRandomSeed = ditherRandomSeed;
// Assert for formats that have not been implemented yet because hardware verification is pending.
assert((nativeCB.siz != G_IM_SIZ_4b) && "Unimplemented 4 bits Writeback mode.");

View File

@ -54,7 +54,7 @@ namespace RT64 {
// Returns the amount of different pixels.
uint32_t copyFromRAM(RenderWorker *worker, FramebufferChange &emptyFbChange, uint32_t width, uint32_t height, uint32_t rowStart, uint8_t siz, uint8_t fmt, const uint8_t *data, bool invalidateTargets, const ShaderLibrary *shaderLibrary);
void copyToNative(RenderWorker *worker, RenderTarget *srcTarget, uint32_t rowWidth, uint32_t rowStart, uint32_t rowEnd, uint8_t siz, uint8_t fmt, const ShaderLibrary *shaderLibrary);
void copyToNative(RenderWorker *worker, RenderTarget *srcTarget, uint32_t rowWidth, uint32_t rowStart, uint32_t rowEnd, uint8_t siz, uint8_t fmt, uint32_t ditherPattern, uint32_t ditherRandomSeed, const ShaderLibrary *shaderLibrary);
void copyToRAM(uint32_t rowStart, uint32_t rowEnd, uint32_t width, uint8_t siz, uint8_t *data);
static uint32_t getNativeSize(uint32_t width, uint32_t height, uint8_t siz);

View File

@ -7,6 +7,7 @@
#include "shared/rt64_fb_reinterpret.h"
#include "Depth.hlsli"
#include "Random.hlsli"
#include "TextureDecoder.hlsli"
[[vk::push_constant]] ConstantBuffer<FbReinterpretCB> gConstants : register(b0);
@ -16,7 +17,10 @@ RWTexture2D<float4> gOutput : register(u3);
float4 RGBA16toCI8(float4 inputColor, uint2 inputCoord, uint2 outputCoord) {
// Drop down the input color to its RGBA16 version.
uint nativeColor = Float4ToRGBA16(inputColor);
uint2 ditherCoord = inputCoord + gConstants.ditherOffset;
uint randomSeed = initRand(gConstants.ditherRandomSeed, ditherCoord.y * gConstants.resolution.x + ditherCoord.x, 16);
uint ditherValue = DitherPatternValue(gConstants.ditherPattern, ditherCoord, randomSeed);
uint nativeColor = Float4ToRGBA16(inputColor, ditherValue);
// Extract the lower or upper half of the value depending on the pixel misalignment.
uint pixelMisalignment = 1 - (outputCoord.x % 2);

View File

@ -3,6 +3,7 @@
//
#include "FbCommon.hlsli"
#include "Random.hlsli"
[[vk::push_constant]] ConstantBuffer<FbCommonCB> gConstants : register(b0, space0);
RWBuffer<uint> gOutput : register(u1, space0);
@ -15,7 +16,9 @@ void CSMain(uint2 coord : SV_DispatchThreadID) {
uint dstIndex = offsetCoord.y * gConstants.resolution.x + offsetCoord.x;
float4 color = gInput.Load(uint3(offsetCoord, 0));
bool oddColumn = (offsetCoord.x & 1);
uint nativeUint = Float4ToUINT(color, gConstants.siz, gConstants.fmt, oddColumn);
uint randomSeed = initRand(gConstants.ditherRandomSeed, dstIndex, 16);
uint ditherValue = DitherPatternValue(gConstants.ditherPattern, offsetCoord, randomSeed);
uint nativeUint = Float4ToUINT(color, gConstants.siz, gConstants.fmt, oddColumn, ditherValue);
gOutput[dstIndex] = EndianSwapUINT(nativeUint, gConstants.siz);
}
}

View File

@ -38,7 +38,7 @@ void RasterPS(const RenderParams rp, bool outputDepth, float4 vertexPosition, fl
const bool depthDecal = (otherMode.zMode() == ZMODE_DEC);
const bool zSourcePrim = (otherMode.zSource() == G_ZS_PRIM);
int2 pixelPosSeed = floor(vertexPosition.xy);
uint randomSeed = initRand(FrParams.frameCount, instanceIndex * pixelPosSeed.x * pixelPosSeed.y, 16);
uint randomSeed = initRand(FrParams.frameCount, instanceIndex * pixelPosSeed.y * pixelPosSeed.x, 16); // TODO: Review seed.
if (outputDepth) {
if (zSourcePrim) {
resultDepth = instanceRDPParams[instanceIndex].primDepth.x;
@ -162,6 +162,23 @@ void RasterPS(const RenderParams rp, bool outputDepth, float4 vertexPosition, fl
ccInputs.K5 = (instanceRDPParams[instanceIndex].convertK[5] / 255.0f);
colorCombiner.run(ccInputs, combinerColor, alphaCompareValue);
#if 0
// Alpha dither.
// TODO: To avoid increasing the alpha values here, the only viable choice would be to drop the precision down to 5-bit.
// Since we'd rather keep the full precision of the alpha channel from the texture, this step is ignored for now.
if (otherMode.alphaDither() != G_AD_DISABLE) {
uint rgbDither = (otherMode.rgbDither() >> G_MDSFT_RGBDITHER) & 0x3;
uint alphaDither = (otherMode.alphaDither() >> G_MDSFT_ALPHADITHER) & 0x3;
float alphaDitherFloat = (AlphaDitherValue(rgbDither, alphaDither, floor(vertexPosition.xy), randomSeed) / 255.0f);
if (!otherMode.alphaCvgSel()) {
combinerColor.a += alphaDitherFloat;
}
shadeColor.a += alphaDitherFloat;
alphaCompareValue += alphaDitherFloat;
}
#endif
// Alpha compare.
if (otherMode.alphaCompare() == G_AC_DITHER) {
if (alphaCompareValue < nextRand(randomSeed)) {

View File

@ -17,7 +17,7 @@ float4 PSMain(in float4 pos : SV_Position, in float2 uv : TEXCOORD0, in uint sam
#else
float4 inputColor = gInput.Load(uint3(pos.xy, 0));
#endif
uint rgba16 = Float4ToRGBA16(inputColor);
uint rgba16 = Float4ToRGBA16(inputColor, 0);
resultDepth = Depth16ToFloat(rgba16);
return 0.0f;
}

View File

@ -13,6 +13,18 @@
#define G_ZS_PIXEL (0 << G_MDSFT_ZSRCSEL)
#define G_ZS_PRIM (1 << G_MDSFT_ZSRCSEL)
#define G_MDSFT_ALPHADITHER 4
#define G_AD_PATTERN (0 << G_MDSFT_ALPHADITHER)
#define G_AD_NOTPATTERN (1 << G_MDSFT_ALPHADITHER)
#define G_AD_NOISE (2 << G_MDSFT_ALPHADITHER)
#define G_AD_DISABLE (3 << G_MDSFT_ALPHADITHER)
#define G_MDSFT_RGBDITHER 6
#define G_CD_MAGICSQ (0 << G_MDSFT_RGBDITHER)
#define G_CD_BAYER (1 << G_MDSFT_RGBDITHER)
#define G_CD_NOISE (2 << G_MDSFT_RGBDITHER)
#define G_CD_DISABLE (3 << G_MDSFT_RGBDITHER)
#define G_MDSFT_COMBKEY 8
#define G_CK_NONE (0 << G_MDSFT_COMBKEY)
#define G_CK_KEY (1 << G_MDSFT_COMBKEY)

View File

@ -16,6 +16,8 @@ namespace interop {
uint2 resolution;
uint fmt;
uint siz;
uint ditherPattern;
uint ditherRandomSeed;
};
#ifdef HLSL_CPU
};

View File

@ -17,6 +17,9 @@ namespace interop {
uint dstSiz;
uint dstFmt;
uint tlutFormat;
uint ditherPattern;
uint ditherRandomSeed;
uint2 ditherOffset;
};
#ifdef HLSL_CPU
};

View File

@ -71,6 +71,14 @@ namespace interop {
return H & (3U << G_MDSFT_TEXTLUT);
}
uint alphaDither() constmethod {
return H & (3U << G_MDSFT_ALPHADITHER);
}
uint rgbDither() constmethod {
return H & (3U << G_MDSFT_RGBDITHER);
}
bool aaEn() constmethod {
return L & AA_EN;
}