vulkan: fog support

This commit is contained in:
Flyinghead 2019-10-06 17:02:17 +02:00
parent 8f8f270cfc
commit b82a97853f
7 changed files with 59 additions and 25 deletions

View File

@ -1,6 +1,7 @@
#pragma once
#include <atomic>
#include "oslib/oslib.h"
#include "hw/pvr/pvr_regs.h"
#include "hw/pvr/ta_structs.h"
extern u8* vq_codebook;
@ -630,7 +631,7 @@ struct PvrTexInfo;
template <class pixel_type> class PixelBuffer;
typedef void TexConvFP(PixelBuffer<u16>* pb,u8* p_in,u32 Width,u32 Height);
typedef void TexConvFP32(PixelBuffer<u32>* pb,u8* p_in,u32 Width,u32 Height);
enum class TextureType { _565, _5551, _4444, _8888 };
enum class TextureType { _565, _5551, _4444, _8888, _8 };
struct BaseTextureCacheData
{
@ -705,3 +706,13 @@ void CollectCleanup();
void killtex();
void ReadFramebuffer(PixelBuffer<u32>& pb, int& width, int& height);
static inline void MakeFogTexture(u8 *tex_data)
{
u8 *fog_table = (u8 *)FOG_TABLE;
for (int i = 0; i < 128; i++)
{
tex_data[i] = fog_table[i * 4];
tex_data[i + 128] = fog_table[i * 4 + 1];
}
}

View File

@ -1387,11 +1387,8 @@ void UpdateFogTexture(u8 *fog_table, GLenum texture_slot, GLint fog_image_format
glcache.BindTexture(GL_TEXTURE_2D, fogTextureId);
u8 temp_tex_buffer[256];
for (int i = 0; i < 128; i++)
{
temp_tex_buffer[i] = fog_table[i * 4];
temp_tex_buffer[i + 128] = fog_table[i * 4 + 1];
}
MakeFogTexture(temp_tex_buffer);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, fog_image_format, 128, 2, 0, fog_image_format, GL_UNSIGNED_BYTE, temp_tex_buffer);
glCheck();

View File

@ -202,7 +202,7 @@ void PipelineManager::CreatePipeline(u32 listType, bool sortTriangles, const Pol
params.clipTest = 0; // always passes
break;
}
params.fog = 2; // TODO fog texture -> pp.tsp.FogCtrl;
params.fog = settings.rend.Fog ? pp.tsp.FogCtrl : 2;
params.gouraud = pp.pcw.Gouraud;
params.ignoreTexAlpha = pp.tsp.IgnoreTexA;
params.offset = pp.pcw.Offset;

View File

@ -50,7 +50,7 @@ public:
vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), ARRAY_SIZE(layouts), layouts, 1, &pushConstant));
}
void UpdateUniforms(const vk::Buffer& vertexUniformBuffer, const vk::Buffer& fragmentUniformBuffer)
void UpdateUniforms(const vk::Buffer& vertexUniformBuffer, const vk::Buffer& fragmentUniformBuffer, vk::ImageView fogImageView)
{
while (perFrameDescSets.empty())
{
@ -63,12 +63,24 @@ public:
while (perPolyDescSetsInFlight.size() < GetContext()->GetSwapChainSize())
perPolyDescSetsInFlight.push_back(std::map<std::pair<u64, u32>, vk::UniqueDescriptorSet>());
int currentImage = GetContext()->GetCurrentImageIndex();
std::vector<vk::DescriptorBufferInfo> bufferInfos;
bufferInfos.push_back(vk::DescriptorBufferInfo(vertexUniformBuffer, 0, VK_WHOLE_SIZE));
bufferInfos.push_back(vk::DescriptorBufferInfo(fragmentUniformBuffer, 0, VK_WHOLE_SIZE));
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
writeDescriptorSets.push_back(vk::WriteDescriptorSet(*perFrameDescSets[currentImage], 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfos[0], nullptr));
writeDescriptorSets.push_back(vk::WriteDescriptorSet(*perFrameDescSets[currentImage], 1, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfos[1], nullptr));
if (fogImageView)
{
TSP fogTsp = {};
fogTsp.FilterMode = 1;
fogTsp.ClampU = 1;
fogTsp.ClampV = 1;
vk::Sampler fogSampler = samplerManager.GetSampler(fogTsp);
vk::DescriptorImageInfo imageInfo(fogSampler, fogImageView, vk::ImageLayout::eShaderReadOnlyOptimal);
writeDescriptorSets.push_back(vk::WriteDescriptorSet(*perFrameDescSets[currentImage], 2, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr));
}
GetContext()->GetDevice()->updateDescriptorSets(writeDescriptorSets, nullptr);
}
@ -176,7 +188,7 @@ private:
| ((pp->tileclip >> 28) << 4);
hash |= ((listType >> 1) << 6);
hash |= (pp->tsp.ShadInstr << 8) | (pp->tsp.IgnoreTexA << 10) | (pp->tsp.UseAlpha << 11)
| (pp->tsp.ColorClamp << 12) | (pp->tsp.FogCtrl << 13) | (pp->tsp.SrcInstr << 15)
| (pp->tsp.ColorClamp << 12) | ((settings.rend.Fog ? pp->tsp.FogCtrl : 2) << 13) | (pp->tsp.SrcInstr << 15)
| (pp->tsp.DstInstr << 18);
hash |= (pp->isp.ZWriteDis << 21) | (pp->isp.CullMode << 22) | (pp->isp.DepthMode << 24);
hash |= (u32)sortTriangles << 27;

View File

@ -129,20 +129,20 @@ layout (location = 1) INTERPOLATION in lowp vec4 vtx_offs;
layout (location = 2) in mediump vec2 vtx_uv;
#if pp_FogCtrl != 2
layout (set = 1, binding = 1) uniform sampler2D fog_table;
layout (set = 0, binding = 2) uniform sampler2D fog_table;
lowp float fog_mode2(float w)
float fog_mode2(float w)
{
float z = clamp(w * uniformBuffer.extra_depth_scale * uniformBuffer.sp_FOG_DENSITY, 1.0, 255.9999);
float exp = floor(log2(z));
float m = z * 16.0 / pow(2.0, exp) - 16.0;
lowp float idx = floor(m) + exp * 16.0 + 0.5;
float idx = floor(m) + exp * 16.0 + 0.5;
vec4 fog_coef = texture(fog_table, vec2(idx / 128.0, 0.75 - (m - floor(m)) / 2.0));
return fog_coef.r;
}
#endif
vec4 colorClamp(lowp vec4 col)
vec4 colorClamp(vec4 col)
{
#if ColorClamping == 1
return clamp(col, uniformBuffer.colorClampMin, uniformBuffer.colorClampMax);
@ -166,7 +166,7 @@ void main()
discard;
#endif
lowp vec4 color = vtx_base;
vec4 color = vtx_base;
#if pp_UseAlpha == 0
color.a = 1.0;
#endif
@ -175,7 +175,7 @@ void main()
#endif
#if pp_Texture == 1
{
lowp vec4 texcol = texture(tex, vtx_uv);
vec4 texcol = texture(tex, vtx_uv);
#if pp_BumpMap == 1
float s = PI / 2.0 * (texcol.a * 15.0 * 16.0 + texcol.r * 15.0) / 255.0;
@ -260,7 +260,7 @@ out vec4 FragColor;
layout (std140, binding = 1) uniform buffer
{
lowp float sp_ShaderColor;
float sp_ShaderColor;
} uniformBuffer;
void main()

View File

@ -145,6 +145,10 @@ void Texture::UploadToGPU(int width, int height, u8 *data)
format = vk::Format::eR8G8B8A8Unorm;
dataSize *= 2;
break;
case TextureType::_8:
format = vk::Format::eR8Unorm;
dataSize /= 2;
break;
}
Init(width, height, format);
SetImage(VulkanContext::Instance()->GetCurrentCommandPool(), dataSize, data);

View File

@ -195,11 +195,8 @@ public:
fragUniforms.colorClampMax[2] = ((pvrrc.fog_clamp_max >> 0) & 0xFF) / 255.0f;
fragUniforms.colorClampMax[3] = ((pvrrc.fog_clamp_max >> 24) & 0xFF) / 255.0f;
if (fog_needs_update && settings.rend.Fog)
{
fog_needs_update = false;
// TODO UpdateFogTexture((u8 *)FOG_TABLE, GL_TEXTURE1, gl.fog_image_format);
}
CheckFogTexture();
fragUniforms.cp_AlphaTestValue = (PT_ALPHA_REF & 0xFF) / 255.0f;
ModVolShaderUniforms modVolUniforms;
@ -207,8 +204,6 @@ public:
UploadUniforms(vtxUniforms, fragUniforms, modVolUniforms);
// TODO this upload should go in a cmd buffer?
GetContext()->BeginRenderPass();
vk::CommandBuffer cmdBuffer = GetContext()->GetCurrentCommandBuffer();
@ -220,7 +215,7 @@ public:
indexBuffers[GetCurrentImage()]->upload(GetContext()->GetDevice().get(), pvrrc.idx.bytes(), pvrrc.idx.head());
// Update per-frame descriptor set and bind it
pipelineManager.GetDescriptorSets().UpdateUniforms(*vertexUniformBuffer, *fragmentUniformBuffer);
pipelineManager.GetDescriptorSets().UpdateUniforms(*vertexUniformBuffer, *fragmentUniformBuffer, fogTexture->GetImageView());
pipelineManager.GetDescriptorSets().BindPerFrameDescriptorSets(cmdBuffer);
// Reset per-poly descriptor set pool
pipelineManager.GetDescriptorSets().Reset();
@ -379,7 +374,6 @@ private:
return clip_mode;
}
void DrawList(const vk::CommandBuffer& cmdBuffer, u32 listType, bool sortTriangles, const List<PolyParam>& polys, u32 first, u32 count)
{
for (u32 i = first; i < count; i++)
@ -492,9 +486,25 @@ private:
}
}
void CheckFogTexture()
{
if (!fogTexture)
{
fogTexture = std::unique_ptr<Texture>(new Texture(GetContext()->GetPhysicalDevice(), *GetContext()->GetDevice()));
fogTexture->tex_type = TextureType::_8;
}
if (!fog_needs_update || !settings.rend.Fog)
return;
fog_needs_update = false;
u8 texData[256];
MakeFogTexture(texData);
fogTexture->UploadToGPU(128, 2, texData);
}
// temp stuff
float scale_x;
float scale_y;
std::unique_ptr<Texture> fogTexture;
// Uniforms
vk::UniqueBuffer vertexUniformBuffer;