GPU/HW: Add fallback path for no-texture-buffers
Yay, old Mali drivers without SSBOs...
This commit is contained in:
parent
4942964e2f
commit
5ef2ba0eb2
|
@ -645,10 +645,15 @@ bool GPU_HW::CreateBuffers()
|
|||
GL_OBJECT_NAME(m_vram_read_texture, "VRAM Read Texture");
|
||||
GL_OBJECT_NAME(m_vram_readback_texture, "VRAM Readback Texture");
|
||||
|
||||
if (!(m_vram_upload_buffer =
|
||||
g_gpu_device->CreateTextureBuffer(GPUTextureBuffer::Format::R16UI, GPUDevice::MIN_TEXEL_BUFFER_ELEMENTS)))
|
||||
if (g_gpu_device->GetFeatures().supports_texture_buffers)
|
||||
{
|
||||
return false;
|
||||
if (!(m_vram_upload_buffer =
|
||||
g_gpu_device->CreateTextureBuffer(GPUTextureBuffer::Format::R16UI, GPUDevice::MIN_TEXEL_BUFFER_ELEMENTS)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_OBJECT_NAME(m_vram_upload_buffer, "VRAM Upload Buffer");
|
||||
}
|
||||
|
||||
Log_InfoFmt("Created HW framebuffer of {}x{}", texture_width, texture_height);
|
||||
|
@ -999,9 +1004,10 @@ bool GPU_HW::CompilePipelines()
|
|||
|
||||
// VRAM write
|
||||
{
|
||||
const bool use_buffer = features.supports_texture_buffers;
|
||||
const bool use_ssbo = features.texture_buffers_emulated_with_ssbo;
|
||||
std::unique_ptr<GPUShader> fs =
|
||||
g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GenerateVRAMWriteFragmentShader(use_ssbo));
|
||||
std::unique_ptr<GPUShader> fs = g_gpu_device->CreateShader(
|
||||
GPUShaderStage::Fragment, shadergen.GenerateVRAMWriteFragmentShader(use_buffer, use_ssbo));
|
||||
if (!fs)
|
||||
return false;
|
||||
|
||||
|
@ -2438,11 +2444,28 @@ void GPU_HW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, b
|
|||
}
|
||||
}
|
||||
|
||||
const u32 num_pixels = width * height;
|
||||
void* map = m_vram_upload_buffer->Map(num_pixels);
|
||||
const u32 map_index = m_vram_upload_buffer->GetCurrentPosition();
|
||||
std::memcpy(map, data, num_pixels * sizeof(u16));
|
||||
m_vram_upload_buffer->Unmap(num_pixels);
|
||||
std::unique_ptr<GPUTexture> upload_texture;
|
||||
u32 map_index;
|
||||
|
||||
if (!g_gpu_device->GetFeatures().supports_texture_buffers)
|
||||
{
|
||||
map_index = 0;
|
||||
upload_texture = g_gpu_device->FetchTexture(width, height, 1, 1, 1, GPUTexture::Type::Texture,
|
||||
GPUTexture::Format::R16U, data, width * sizeof(u16));
|
||||
if (!upload_texture)
|
||||
{
|
||||
Log_ErrorFmt("Failed to get {}x{} upload texture. Things are gonna break.", width, height);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 num_pixels = width * height;
|
||||
void* map = m_vram_upload_buffer->Map(num_pixels);
|
||||
map_index = m_vram_upload_buffer->GetCurrentPosition();
|
||||
std::memcpy(map, data, num_pixels * sizeof(u16));
|
||||
m_vram_upload_buffer->Unmap(num_pixels);
|
||||
}
|
||||
|
||||
struct VRAMWriteUBOData
|
||||
{
|
||||
|
@ -2465,8 +2488,17 @@ void GPU_HW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, b
|
|||
g_gpu_device->SetScissor(scaled_bounds.left, scaled_bounds.top, scaled_bounds.GetWidth(), scaled_bounds.GetHeight());
|
||||
g_gpu_device->SetPipeline(m_vram_write_pipelines[BoolToUInt8(check_mask && !m_pgxp_depth_buffer)].get());
|
||||
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
|
||||
g_gpu_device->SetTextureBuffer(0, m_vram_upload_buffer.get());
|
||||
g_gpu_device->Draw(3, 0);
|
||||
if (upload_texture)
|
||||
{
|
||||
g_gpu_device->SetTextureSampler(0, upload_texture.get(), g_gpu_device->GetNearestSampler());
|
||||
g_gpu_device->Draw(3, 0);
|
||||
g_gpu_device->RecycleTexture(std::move(upload_texture));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_gpu_device->SetTextureBuffer(0, m_vram_upload_buffer.get());
|
||||
g_gpu_device->Draw(3, 0);
|
||||
}
|
||||
|
||||
RestoreDeviceContext();
|
||||
}
|
||||
|
|
|
@ -1271,18 +1271,23 @@ uint SampleVRAM(uint2 coords)
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GPU_HW_ShaderGen::GenerateVRAMWriteFragmentShader(bool use_ssbo)
|
||||
std::string GPU_HW_ShaderGen::GenerateVRAMWriteFragmentShader(bool use_buffer, bool use_ssbo)
|
||||
{
|
||||
std::stringstream ss;
|
||||
WriteHeader(ss);
|
||||
WriteCommonFunctions(ss);
|
||||
DefineMacro(ss, "PGXP_DEPTH", m_pgxp_depth);
|
||||
DefineMacro(ss, "USE_BUFFER", use_buffer);
|
||||
DeclareUniformBuffer(ss,
|
||||
{"uint2 u_base_coords", "uint2 u_end_coords", "uint2 u_size", "uint u_buffer_base_offset",
|
||||
"uint u_mask_or_bits", "float u_depth_value"},
|
||||
true);
|
||||
|
||||
if (use_ssbo && m_glsl)
|
||||
if (!use_buffer)
|
||||
{
|
||||
DeclareTexture(ss, "samp0", 0, false, true, true);
|
||||
}
|
||||
else if (use_ssbo && m_glsl)
|
||||
{
|
||||
ss << "layout(std430";
|
||||
if (IsVulkan())
|
||||
|
@ -1316,14 +1321,17 @@ std::string GPU_HW_ShaderGen::GenerateVRAMWriteFragmentShader(bool use_ssbo)
|
|||
discard;
|
||||
}
|
||||
|
||||
|
||||
// find offset from the start of the row/column
|
||||
uint2 offset;
|
||||
offset.x = (coords.x < u_base_coords.x) ? ((VRAM_SIZE.x / RESOLUTION_SCALE) - u_base_coords.x + coords.x) : (coords.x - u_base_coords.x);
|
||||
offset.y = (coords.y < u_base_coords.y) ? ((VRAM_SIZE.y / RESOLUTION_SCALE) - u_base_coords.y + coords.y) : (coords.y - u_base_coords.y);
|
||||
|
||||
#if !USE_BUFFER
|
||||
uint value = LOAD_TEXTURE(samp0, int2(offset), 0).x;
|
||||
#else
|
||||
uint buffer_offset = u_buffer_base_offset + (offset.y * u_size.x) + offset.x;
|
||||
uint value = GET_VALUE(buffer_offset) | u_mask_or_bits;
|
||||
#endif
|
||||
|
||||
o_col0 = RGBA5551ToRGBA8(value);
|
||||
#if !PGXP_DEPTH
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
std::string GenerateWireframeGeometryShader();
|
||||
std::string GenerateWireframeFragmentShader();
|
||||
std::string GenerateVRAMReadFragmentShader();
|
||||
std::string GenerateVRAMWriteFragmentShader(bool use_ssbo);
|
||||
std::string GenerateVRAMWriteFragmentShader(bool use_buffer, bool use_ssbo);
|
||||
std::string GenerateVRAMCopyFragmentShader();
|
||||
std::string GenerateVRAMFillFragmentShader(bool wrapped, bool interlaced);
|
||||
std::string GenerateVRAMUpdateDepthFragmentShader();
|
||||
|
|
|
@ -492,10 +492,7 @@ bool OpenGLDevice::CheckFeatures(bool* buggy_pbo, FeatureMask disabled_features)
|
|||
}
|
||||
else
|
||||
{
|
||||
Host::ReportErrorAsync(
|
||||
TRANSLATE_SV("GPUDevice", "Error"),
|
||||
TRANSLATE_SV("Error", "Both texture buffers and SSBOs are not supported, or are of inadequate size."));
|
||||
return false;
|
||||
Log_WarningPrint("Both texture buffers and SSBOs are not supported. Performance will suffer.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue