- backend update from GZDoom.

This commit is contained in:
Christoph Oelckers 2021-04-05 16:32:45 +02:00
parent 008391a2ad
commit 96fb96617f
10 changed files with 244 additions and 32 deletions

View file

@ -85,17 +85,17 @@ CUSTOM_CVAR(Bool, adl_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUA
FORWARD_BOOL_CVAR(adl_fullpan);
}
CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_VIRTUAL)
{
FORWARD_CVAR(adl_bank);
}
CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_VIRTUAL)
{
FORWARD_BOOL_CVAR(adl_use_custom_bank);
}
CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL)
{
FORWARD_STRING_CVAR(adl_custom_bank);
}
@ -261,12 +261,12 @@ CUSTOM_CVAR(Bool, opn_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUA
FORWARD_BOOL_CVAR(opn_fullpan);
}
CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_VIRTUAL)
{
FORWARD_BOOL_CVAR(opn_use_custom_bank);
}
CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL)
{
FORWARD_STRING_CVAR(opn_custom_bank);
}

View file

@ -175,10 +175,11 @@ void I_PrintStr(const char *cp)
{
const char * srcp = cp;
FString printData = "";
bool terminal = isatty(STDOUT_FILENO);
while (*srcp != 0)
{
if (*srcp == 0x1c && con_printansi)
if (*srcp == 0x1c && con_printansi && terminal)
{
srcp += 1;
EColorRange range = V_ParseFontColor((const uint8_t*&)srcp, CR_UNTRANSLATED, CR_YELLOW);
@ -224,7 +225,7 @@ void I_PrintStr(const char *cp)
if (StartScreen) CleanProgressBar();
fputs(printData.GetChars(),stdout);
fputs("\033[0m",stdout);
if (terminal) fputs("\033[0m",stdout);
if (StartScreen) RedrawProgressBar(ProgressBarCurPos,ProgressBarMaxPos);
}

View file

@ -152,6 +152,10 @@ void PolyFrameBuffer::FlushDrawCommands()
}
}
EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast)
EXTERN_CVAR(Float, vid_saturation)
void PolyFrameBuffer::Update()
{
twoD.Reset();
@ -177,8 +181,9 @@ void PolyFrameBuffer::Update()
if (dst)
{
#if 1
// [GEC] with the help of dpJudas a new system of copying and applying gamma in the video buffer
auto copyqueue = std::make_shared<DrawerCommandQueue>(&mFrameMemory);
copyqueue->Push<MemcpyCommand>(dst, pitch / pixelsize, src, w, h, w, pixelsize);
copyqueue->Push<CopyAndApplyGammaCommand>(dst, pitch / pixelsize, src, w, h, w, vid_gamma, vid_contrast, vid_brightness, vid_saturation);
DrawerThreads::Execute(copyqueue);
#else
for (int y = 0; y < h; y++)
@ -366,6 +371,40 @@ FTexture *PolyFrameBuffer::WipeEndScreen()
TArray<uint8_t> PolyFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma)
{
// [GEC] Really necessary to apply gamma, brightness, contrast and saturation for screenshot
std::vector<uint8_t> gammatablebuf(256);
uint8_t* gammatable = gammatablebuf.data();
float InvGamma = 1.0f / clamp<float>(vid_gamma, 0.1f, 4.f);
float Brightness = clamp<float>(vid_brightness, -0.8f, 0.8f);
float Contrast = clamp<float>(vid_contrast, 0.1f, 3.f);
float Saturation = clamp<float>(vid_saturation, -15.0f, 15.f);
for (int x = 0; x < 256; x++)
{
float ramp = (float)(x / 255.f);
// Apply Contrast
// vec4 finalColor = vec4((((originalColor.rgb - vec3(0.5)) * Contrast) + vec3(0.5)), 1.0);
if(vid_contrast != 1.0f)
ramp = (((ramp - 0.5f) * Contrast) + 0.5f);
// Apply Brightness
// vec4 finalColor = vec4(originalColor.rgb + Brightness, 1.0);
if (vid_brightness != 0.0f)
ramp += (Brightness / 2.0f);
// Apply Gamma
// FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma));
if (vid_gamma != 1.0f)
ramp = pow(ramp, InvGamma);
// Clamp ramp
ramp = clamp<float>(ramp, 0.0f, 1.f);
gammatable[x] = (uint8_t)(ramp * 255);
}
int w = SCREENWIDTH;
int h = SCREENHEIGHT;
@ -380,9 +419,44 @@ TArray<uint8_t> PolyFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_
for (int x = 0; x < w; x++)
{
ScreenshotBuffer[dindex ] = pixels[sindex + 2];
ScreenshotBuffer[dindex + 1] = pixels[sindex + 1];
ScreenshotBuffer[dindex + 2] = pixels[sindex ];
uint32_t red = pixels[sindex + 2];
uint32_t green = pixels[sindex + 1];
uint32_t blue = pixels[sindex];
if (vid_saturation != 1.0f)
{
float NewR = (float)(red / 255.f);
float NewG = (float)(green / 255.f);
float NewB = (float)(blue / 255.f);
// Apply Saturation
// float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750));
// Out = luma.xxx + Saturation.xxx * (In - luma.xxx);
//float luma = (NewR * 0.2126729f) + (NewG * 0.7151522f) + (NewB * 0.0721750f); // Rec. 709
float luma = (NewR * 0.299f) + (NewG * 0.587f) + (NewB * 0.114f); //Rec. 601
NewR = luma + (Saturation * (NewR - luma));
NewG = luma + (Saturation * (NewG - luma));
NewB = luma + (Saturation * (NewB - luma));
// Clamp All
NewR = clamp<float>(NewR, 0.0f, 1.f);
NewG = clamp<float>(NewG, 0.0f, 1.f);
NewB = clamp<float>(NewB, 0.0f, 1.f);
red = (uint32_t)(NewR * 255.f);
green = (uint32_t)(NewG * 255.f);
blue = (uint32_t)(NewB * 255.f);
}
// Apply Contrast / Brightness / Gamma
red = gammatable[red];
green = gammatable[green];
blue = gammatable[blue];
ScreenshotBuffer[dindex ] = red;
ScreenshotBuffer[dindex + 1] = green;
ScreenshotBuffer[dindex + 2] = blue;
dindex += 3;
sindex += 4;
}

View file

@ -96,3 +96,119 @@ private:
};
inline PolyFrameBuffer *GetPolyFrameBuffer() { return static_cast<PolyFrameBuffer*>(screen); }
// [GEC] Original code of dpJudas, I add the formulas of gamma, brightness, contrast and saturation.
class CopyAndApplyGammaCommand : public DrawerCommand
{
public:
CopyAndApplyGammaCommand(void* dest, int destpitch, const void* src, int width, int height, int srcpitch,
float gamma, float contrast, float brightness, float saturation) : dest(dest), src(src), destpitch(destpitch), width(width), height(height), srcpitch(srcpitch),
gamma(gamma), contrast(contrast), brightness(brightness), saturation(saturation)
{
}
void Execute(DrawerThread* thread)
{
float Saturation = clamp<float>(saturation, -15.0f, 15.f);
std::vector<uint8_t> gammatablebuf(256);
uint8_t* gammatable = gammatablebuf.data();
InitGammaTable(gammatable);
int w = width;
int start = thread->skipped_by_thread(0);
int count = thread->count_for_thread(0, height);
int sstep = thread->num_cores * srcpitch;
int dstep = thread->num_cores * destpitch;
uint32_t* d = (uint32_t*)dest + start * destpitch;
const uint32_t* s = (const uint32_t*)src + start * srcpitch;
for (int y = 0; y < count; y++)
{
for (int x = 0; x < w; x++)
{
uint32_t red = RPART(s[x]);
uint32_t green = GPART(s[x]);
uint32_t blue = BPART(s[x]);
uint32_t alpha = APART(s[x]);
if (saturation != 1.0f)
{
float NewR = (float)(red / 255.f);
float NewG = (float)(green / 255.f);
float NewB = (float)(blue / 255.f);
// Apply Saturation
// float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750));
// Out = luma.xxx + Saturation.xxx * (In - luma.xxx);
//float luma = (NewR * 0.2126729f) + (NewG * 0.7151522f) + (NewB * 0.0721750f); // Rec. 709
float luma = (NewR * 0.299f) + (NewG * 0.587f) + (NewB * 0.114f); //Rec. 601
NewR = luma + (Saturation * (NewR - luma));
NewG = luma + (Saturation * (NewG - luma));
NewB = luma + (Saturation * (NewB - luma));
// Clamp All
NewR = clamp<float>(NewR, 0.0f, 1.f);
NewG = clamp<float>(NewG, 0.0f, 1.f);
NewB = clamp<float>(NewB, 0.0f, 1.f);
red = (uint32_t)(NewR * 255.f);
green = (uint32_t)(NewG * 255.f);
blue = (uint32_t)(NewB * 255.f);
}
// Apply Contrast / Brightness / Gamma
red = gammatable[red];
green = gammatable[green];
blue = gammatable[blue];
d[x] = MAKEARGB(alpha, (uint8_t)red, (uint8_t)green, (uint8_t)blue);
}
d += dstep;
s += sstep;
}
}
private:
void InitGammaTable(uint8_t *gammatable)
{
float InvGamma = 1.0f / clamp<float>(gamma, 0.1f, 4.f);
float Brightness = clamp<float>(brightness, -0.8f, 0.8f);
float Contrast = clamp<float>(contrast, 0.1f, 3.f);
for (int x = 0; x < 256; x++)
{
float ramp = (float)(x / 255.f);
// Apply Contrast
// vec4 finalColor = vec4((((originalColor.rgb - vec3(0.5)) * Contrast) + vec3(0.5)), 1.0);
if (contrast != 1.0f)
ramp = (((ramp - 0.5f) * Contrast) + 0.5f);
// Apply Brightness
// vec4 finalColor = vec4(originalColor.rgb + Brightness, 1.0);
if (brightness != 0.0f)
ramp += (Brightness / 2.0f);
// Apply Gamma
// FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma));
if (gamma != 1.0f)
ramp = pow(ramp, InvGamma);
// Clamp ramp
ramp = clamp<float>(ramp, 0.0f, 1.f);
gammatable[x] = (uint8_t)(ramp * 255);
}
}
void* dest;
const void* src;
int destpitch;
int width;
int height;
int srcpitch;
float gamma;
float contrast;
float brightness;
float saturation;
};

View file

@ -538,12 +538,13 @@ static void MainFP(int x0, int x1, PolyTriangleThreadData* thread)
// frag = frag * vColor;
// frag.rgb = frag.rgb + uFogColor.rgb;
uint32_t startR = (int)((thread->mainVertexShader.Data.uObjectColor.r) * 255.0f);
uint32_t startG = (int)((thread->mainVertexShader.Data.uObjectColor.g) * 255.0f);
uint32_t startB = (int)((thread->mainVertexShader.Data.uObjectColor.b) * 255.0f);
uint32_t rangeR = (int)((thread->mainVertexShader.Data.uAddColor.r) * 255.0f) - startR;
uint32_t rangeG = (int)((thread->mainVertexShader.Data.uAddColor.g) * 255.0f) - startG;
uint32_t rangeB = (int)((thread->mainVertexShader.Data.uAddColor.b) * 255.0f) - startB;
// [GEC] I leave the default floating values.
float startR = thread->mainVertexShader.Data.uObjectColor.r;
float startG = thread->mainVertexShader.Data.uObjectColor.g;
float startB = thread->mainVertexShader.Data.uObjectColor.b;
float rangeR = thread->mainVertexShader.Data.uAddColor.r - startR;
float rangeG = thread->mainVertexShader.Data.uAddColor.g - startG;
float rangeB = thread->mainVertexShader.Data.uAddColor.b - startB;
for (int x = x0; x < x1; x++)
{
@ -555,15 +556,22 @@ static void MainFP(int x0, int x1, PolyTriangleThreadData* thread)
uint32_t gray = (r * 77 + g * 143 + b * 37) >> 8;
gray += (gray >> 7); // gray*=256/255
r = (startR + ((gray * rangeR) >> 8)) << 1;
g = (startG + ((gray * rangeG) >> 8)) << 1;
b = (startB + ((gray * rangeB) >> 8)) << 1;
// [GEC] I use the same method as in shaders using floating values.
// This avoids errors in the invulneravility colormap in Doom and Heretic.
float fgray = (float)(gray / 255.f);
float fr = (startR + (fgray * rangeR)) * 2;
float fg = (startG + (fgray * rangeG)) * 2;
float fb = (startB + (fgray * rangeB)) * 2;
r = MIN(r, (uint32_t)255);
g = MIN(g, (uint32_t)255);
b = MIN(b, (uint32_t)255);
fr = clamp<float>(fr, 0.0f, 1.0f);
fg = clamp<float>(fg, 0.0f, 1.0f);
fb = clamp<float>(fb, 0.0f, 1.0f);
fragcolor[x] = MAKEARGB(a, r, g, b);
r = (uint32_t)(fr * 255.f);
g = (uint32_t)(fg * 255.f);
b = (uint32_t)(fb * 255.f);
fragcolor[x] = MAKEARGB(a, (uint8_t)r, (uint8_t)g, (uint8_t)b);
}
}
else

View file

@ -212,13 +212,18 @@ void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlag
ImageBuilder builder;
builder.setSize(width, height);
builder.setSamples(samples);
builder.setFormat(VK_FORMAT_A2R10G10B10_UNORM_PACK32);
builder.setFormat(SceneNormalFormat);
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
if (!builder.isFormatSupported(fb->device, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
{
SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM;
builder.setFormat(SceneNormalFormat);
}
SceneNormal.Image = builder.create(fb->device);
SceneNormal.Image->SetDebugName("VkRenderBuffers.SceneNormal");
ImageViewBuilder viewbuilder;
viewbuilder.setImage(SceneNormal.Image.get(), VK_FORMAT_A2R10G10B10_UNORM_PACK32);
viewbuilder.setImage(SceneNormal.Image.get(), SceneNormalFormat);
SceneNormal.View = viewbuilder.create(fb->device);
SceneNormal.View->SetDebugName("VkRenderBuffers.SceneNormalView");
}

View file

@ -24,6 +24,7 @@ public:
VkTextureImage SceneFog;
VkFormat SceneDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT;
VkFormat SceneNormalFormat = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
static const int NumPipelineImages = 2;
VkTextureImage PipelineImage[NumPipelineImages];

View file

@ -281,7 +281,7 @@ std::unique_ptr<VulkanRenderPass> VkRenderPassSetup::CreateRenderPass(int clearT
{
auto buffers = GetVulkanFrameBuffer()->GetBuffers();
VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_A2R10G10B10_UNORM_PACK32 };
VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, buffers->SceneNormalFormat };
RenderPassBuilder builder;
@ -420,6 +420,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
builder.setTopology(vktopology[key.DrawType]);
builder.setDepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest);
builder.setDepthFunc(depthfunc2vk[key.DepthFunc]);
if (fb->device->UsedDeviceFeatures.depthClamp)
builder.setDepthClampEnable(key.DepthClamp);
builder.setDepthBias(key.DepthBias, 0.0f, 0.0f, 0.0f);

View file

@ -45,7 +45,7 @@ public:
void setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0);
void setLinearTiling();
bool isFormatSupported(VulkanDevice *device);
bool isFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures = 0);
std::unique_ptr<VulkanImage> create(VulkanDevice *device, VkDeviceSize* allocatedBytes = nullptr);
std::unique_ptr<VulkanImage> tryCreate(VulkanDevice *device);
@ -410,7 +410,7 @@ inline void ImageBuilder::setMemoryType(VkMemoryPropertyFlags requiredFlags, VkM
allocInfo.memoryTypeBits = memoryTypeBits;
}
inline bool ImageBuilder::isFormatSupported(VulkanDevice *device)
inline bool ImageBuilder::isFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures)
{
VkImageFormatProperties properties = { };
VkResult result = vkGetPhysicalDeviceImageFormatProperties(device->PhysicalDevice.Device, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &properties);
@ -421,6 +421,13 @@ inline bool ImageBuilder::isFormatSupported(VulkanDevice *device)
if (imageInfo.mipLevels > properties.maxMipLevels) return false;
if (imageInfo.arrayLayers > properties.maxArrayLayers) return false;
if ((imageInfo.samples & properties.sampleCounts) != imageInfo.samples) return false;
if (bufferFeatures != 0)
{
VkFormatProperties formatProperties = { };
vkGetPhysicalDeviceFormatProperties(device->PhysicalDevice.Device, imageInfo.format, &formatProperties);
if ((formatProperties.bufferFeatures & bufferFeatures) != bufferFeatures)
return false;
}
return true;
}

View file

@ -108,8 +108,7 @@ bool VulkanDevice::CheckRequiredFeatures(const VkPhysicalDeviceFeatures &f)
{
return
f.samplerAnisotropy == VK_TRUE &&
f.fragmentStoresAndAtomics == VK_TRUE &&
f.depthClamp == VK_TRUE;
f.fragmentStoresAndAtomics == VK_TRUE;
}
void VulkanDevice::SelectPhysicalDevice()