Negative noise dither option. (#81)

This commit is contained in:
Darío 2024-09-17 09:11:41 -03:00 committed by GitHub
parent d884392b71
commit 85df6cf053
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 50 additions and 11 deletions

View File

@ -446,6 +446,7 @@ build_compute_shader(rt64 "src/shaders/IdleCS.hlsl")
build_compute_shader(rt64 "src/shaders/LuminanceHistogramCS.hlsl")
build_pixel_shader( rt64 "src/shaders/PostBlendDitherNoisePS.hlsl" "src/shaders/PostBlendDitherNoiseAddPS.hlsl" "-D ADD_MODE")
build_pixel_shader( rt64 "src/shaders/PostBlendDitherNoisePS.hlsl" "src/shaders/PostBlendDitherNoiseSubPS.hlsl" "-D SUB_MODE")
build_pixel_shader( rt64 "src/shaders/PostBlendDitherNoisePS.hlsl" "src/shaders/PostBlendDitherNoiseSubNegativePS.hlsl" "-D SUB_MODE" "-D NEGATIVE_MODE")
build_compute_shader(rt64 "src/shaders/RSPModifyCS.hlsl")
build_compute_shader(rt64 "src/shaders/RSPProcessCS.hlsl")
build_compute_shader(rt64 "src/shaders/RSPWorldCS.hlsl")

View File

@ -9,6 +9,7 @@ namespace RT64 {
EmulatorConfiguration::EmulatorConfiguration() {
dither.postBlendNoise = true;
dither.postBlendNoiseNegative = false;
framebuffer.renderToRAM = true;
framebuffer.copyWithGPU = true;
}

View File

@ -10,6 +10,7 @@ namespace RT64 {
struct EmulatorConfiguration {
struct Dither {
bool postBlendNoise;
bool postBlendNoiseNegative;
};
struct Framebuffer {

View File

@ -1217,6 +1217,7 @@ namespace RT64 {
drawParams.ubershadersOnly = false;
drawParams.fixRectLR = false;
drawParams.postBlendNoise = ext.emulatorConfig->dither.postBlendNoise;
drawParams.postBlendNoiseNegative = ext.emulatorConfig->dither.postBlendNoiseNegative;
drawParams.maxGameCall = UINT_MAX;
framebufferRenderer->addFramebuffer(drawParams);
}
@ -2090,6 +2091,7 @@ namespace RT64 {
ImGui::Text("Dither");
ImGui::Indent();
emulatorConfigChanged = ImGui::Checkbox("Post Blend Noise", &emulatorConfig.dither.postBlendNoise) || emulatorConfigChanged;
emulatorConfigChanged = ImGui::Checkbox("Post Blend Noise Negative", &emulatorConfig.dither.postBlendNoiseNegative) || emulatorConfigChanged;
ImGui::Unindent();
ImGui::Text("Framebuffer");
ImGui::Indent();

View File

@ -248,6 +248,7 @@ namespace RT64 {
workloadConfig.fixRectLR = ext.sharedResources->enhancementConfig.rect.fixRectLR;
workloadConfig.postBlendNoise = ext.sharedResources->emulatorConfig.dither.postBlendNoise;
workloadConfig.postBlendNoiseNegative = ext.sharedResources->emulatorConfig.dither.postBlendNoiseNegative;
if (ext.sharedResources->fbConfigChanged || sizeChanged) {
{
@ -588,6 +589,7 @@ namespace RT64 {
drawParams.ubershadersOnly = ubershadersOnly;
drawParams.fixRectLR = workloadConfig.fixRectLR;
drawParams.postBlendNoise = workloadConfig.postBlendNoise;
drawParams.postBlendNoiseNegative = workloadConfig.postBlendNoiseNegative;
drawParams.maxGameCall = std::min(gameCallCountMax - gameCallCursor, fbPair.gameCallCount);
framebufferRenderer->addFramebuffer(drawParams);
}

View File

@ -57,6 +57,7 @@ namespace RT64 {
uint32_t targetRate = 0;
bool fixRectLR = false;
bool postBlendNoise = false;
bool postBlendNoiseNegative = false;
};
External ext;

View File

@ -580,10 +580,18 @@ namespace RT64 {
worker->commandList->setGraphicsPushConstants(0, &rasterParams);
drawCallTriangles(drawCall);
// Simulate dither noise.
if (triangles.postBlendDitherNoise) {
worker->commandList->setPipeline(postBlendDitherNoiseAddPipeline);
drawCallTriangles(drawCall);
worker->commandList->setPipeline(postBlendDitherNoiseSubPipeline);
if (triangles.postBlendDitherNoiseNegative) {
worker->commandList->setPipeline(postBlendDitherNoiseSubNegativePipeline);
}
else {
worker->commandList->setPipeline(postBlendDitherNoiseAddPipeline);
drawCallTriangles(drawCall);
worker->commandList->setPipeline(postBlendDitherNoiseSubPipeline);
}
drawCallTriangles(drawCall);
previousPipeline = nullptr;
}
@ -1313,12 +1321,15 @@ namespace RT64 {
framebuffer.descDummyFbSet->setTexture(framebuffer.descDummyFbSet->gBackgroundColor, p.fbStorage->colorTarget->getResolvedTexture(), RenderTextureLayout::SHADER_READ, p.fbStorage->colorTarget->getResolvedTextureView());
framebuffer.descDummyFbSet->setTexture(framebuffer.descDummyFbSet->gBackgroundDepth, dummyDepthTarget.get(), RenderTextureLayout::DEPTH_READ, dummyDepthTargetView.get());
// Make a new render target draw call.
RenderTargetDrawCall &targetDrawCall = framebuffer.renderTargetDrawCall;
// Store ubershader and other effect pipelines.
const RasterShaderUber *rasterShaderUber = p.rasterShaderCache->getGPUShaderUber();
rendererPipelineLayout = rasterShaderUber->pipelineLayout.get();
postBlendDitherNoiseAddPipeline = rasterShaderUber->postBlendDitherNoiseAddPipeline.get();
postBlendDitherNoiseSubPipeline = rasterShaderUber->postBlendDitherNoiseSubPipeline.get();
postBlendDitherNoiseSubNegativePipeline = rasterShaderUber->postBlendDitherNoiseSubNegativePipeline.get();
// Make a new render target draw call.
RenderTargetDrawCall &targetDrawCall = framebuffer.renderTargetDrawCall;
const DrawData &drawData = p.curWorkload->drawData;
const DrawBuffers &drawBuffers = p.curWorkload->drawBuffers;
const OutputBuffers &outputBuffers = p.curWorkload->outputBuffers;
@ -1609,6 +1620,7 @@ namespace RT64 {
// Indicate if post blend dither noise should be applied.
bool rgbDitherNoise = (call.shaderDesc.otherMode.rgbDither() == G_CD_NOISE);
triangles.postBlendDitherNoise = rgbDitherNoise && !call.shaderDesc.otherMode.zCmp() && !call.shaderDesc.otherMode.zUpd();
triangles.postBlendDitherNoiseNegative = p.postBlendNoiseNegative;
}
break;

View File

@ -6,6 +6,7 @@
#include <stdint.h>
#include "common/rt64_emulator_configuration.h"
#include "common/rt64_user_configuration.h"
#include "hle/rt64_framebuffer_manager.h"
#include "hle/rt64_workload.h"
@ -85,6 +86,7 @@ namespace RT64 {
RenderPipelineLayout *rendererPipelineLayout = nullptr;
RenderPipeline *postBlendDitherNoiseAddPipeline = nullptr;
RenderPipeline *postBlendDitherNoiseSubPipeline = nullptr;
RenderPipeline *postBlendDitherNoiseSubNegativePipeline = nullptr;
std::unique_ptr<FramebufferRendererDescriptorCommonSet> descCommonSet;
std::unique_ptr<FramebufferRendererDescriptorTextureSet> descTextureSet;
std::unique_ptr<RenderTexture> dummyDepthTarget;
@ -140,6 +142,7 @@ namespace RT64 {
bool ubershadersOnly;
bool fixRectLR;
bool postBlendNoise;
bool postBlendNoiseNegative;
uint32_t maxGameCall;
};

View File

@ -37,8 +37,9 @@ namespace RT64 {
RenderViewport viewport;
uint32_t indexStart;
uint32_t faceCount;
bool vertexTestZ;
bool postBlendDitherNoise;
bool vertexTestZ : 1;
bool postBlendDitherNoise : 1;
bool postBlendDitherNoiseNegative : 1;
} triangles;
struct {

View File

@ -20,6 +20,7 @@
#include "shaders/RasterVSSpecConstantFlat.hlsl.spirv.h"
#include "shaders/PostBlendDitherNoiseAddPS.hlsl.spirv.h"
#include "shaders/PostBlendDitherNoiseSubPS.hlsl.spirv.h"
#include "shaders/PostBlendDitherNoiseSubNegativePS.hlsl.spirv.h"
#ifdef _WIN32
# include "shaders/RasterPSLibrary.hlsl.dxil.h"
# include "shaders/RasterPSLibraryMS.hlsl.dxil.h"
@ -29,6 +30,7 @@
# include "shaders/RasterVSDynamic.hlsl.dxil.h"
# include "shaders/PostBlendDitherNoiseAddPS.hlsl.dxil.h"
# include "shaders/PostBlendDitherNoiseSubPS.hlsl.dxil.h"
# include "shaders/PostBlendDitherNoiseSubNegativePS.hlsl.dxil.h"
#endif
#include "shared/rt64_raster_params.h"
@ -463,16 +465,19 @@ namespace RT64 {
// Create the pipelines for post blend operations.
std::unique_ptr<RenderShader> postBlendAddPixelShader;
std::unique_ptr<RenderShader> postBlendSubPixelShader;
std::unique_ptr<RenderShader> postBlendSubNegativePixelShader;
switch (shaderFormat) {
# ifdef _WIN32
case RenderShaderFormat::DXIL:
postBlendAddPixelShader = device->createShader(PostBlendDitherNoiseAddPSBlobDXIL, std::size(PostBlendDitherNoiseAddPSBlobDXIL), "PSMain", shaderFormat);
postBlendSubPixelShader = device->createShader(PostBlendDitherNoiseSubPSBlobDXIL, std::size(PostBlendDitherNoiseSubPSBlobDXIL), "PSMain", shaderFormat);
postBlendSubNegativePixelShader = device->createShader(PostBlendDitherNoiseSubNegativePSBlobDXIL, std::size(PostBlendDitherNoiseSubNegativePSBlobDXIL), "PSMain", shaderFormat);
break;
# endif
case RenderShaderFormat::SPIRV:
postBlendAddPixelShader = device->createShader(PostBlendDitherNoiseAddPSBlobSPIRV, std::size(PostBlendDitherNoiseAddPSBlobSPIRV), "PSMain", shaderFormat);
postBlendSubPixelShader = device->createShader(PostBlendDitherNoiseSubPSBlobSPIRV, std::size(PostBlendDitherNoiseSubPSBlobSPIRV), "PSMain", shaderFormat);
postBlendSubNegativePixelShader = device->createShader(PostBlendDitherNoiseSubNegativePSBlobSPIRV, std::size(PostBlendDitherNoiseSubNegativePSBlobSPIRV), "PSMain", shaderFormat);
break;
default:
assert(false && "Unknown shader format.");
@ -509,6 +514,9 @@ namespace RT64 {
postBlendDesc.pixelShader = postBlendSubPixelShader.get();
targetBlend.blendOp = RenderBlendOperation::REV_SUBTRACT;
postBlendDitherNoiseSubPipeline = device->createGraphicsPipeline(postBlendDesc);
postBlendDesc.pixelShader = postBlendSubNegativePixelShader.get();
postBlendDitherNoiseSubNegativePipeline = device->createGraphicsPipeline(postBlendDesc);
}
RasterShaderUber::~RasterShaderUber() {

View File

@ -79,6 +79,7 @@ namespace RT64 {
std::unique_ptr<RenderPipeline> pipelines[8];
std::unique_ptr<RenderPipeline> postBlendDitherNoiseAddPipeline;
std::unique_ptr<RenderPipeline> postBlendDitherNoiseSubPipeline;
std::unique_ptr<RenderPipeline> postBlendDitherNoiseSubNegativePipeline;
std::mutex firstPipelineMutex;
std::condition_variable firstPipelineCondition;
bool pipelinesCreated = false;

View File

@ -20,12 +20,18 @@ void PSMain(
int2 pixelPosSeed = floor(vertexPosition.xy);
uint randomSeed = initRand(FrParams.frameCount, gConstants.renderIndex * (pixelPosSeed.y * 65536 + pixelPosSeed.x), 16);
const float Range = (7.0f * FrParams.ditherNoiseStrength) / 255.0f;
const float HalfRange = Range / 2.0f;
resultColor.r = nextRand(randomSeed) * Range - HalfRange;
resultColor.g = nextRand(randomSeed) * Range - HalfRange;
resultColor.b = nextRand(randomSeed) * Range - HalfRange;
resultColor.r = nextRand(randomSeed) * Range;
resultColor.g = nextRand(randomSeed) * Range;
resultColor.b = nextRand(randomSeed) * Range;
resultColor.a = 0.0f;
#if defined(NEGATIVE_MODE)
resultColor.rgb -= Range;
#else
const float HalfRange = Range / 2.0f;
resultColor.rgb -= HalfRange;
#endif
#if defined(ADD_MODE)
resultColor = max(resultColor, 0.0f);
#elif defined(SUB_MODE)