VideoCommon: Fix bounding box on AMD/OpenGL/Windows

Co-authored-by: Techjar <tecknojar@gmail.com>
This commit is contained in:
Pokechu22 2021-05-28 18:10:48 -07:00
parent c404452d3e
commit c58837964f
3 changed files with 36 additions and 9 deletions

View File

@ -126,6 +126,8 @@ constexpr BugInfo m_known_bugs[] = {
-1.0, -1.0, true},
{API_VULKAN, OS_ALL, VENDOR_ARM, DRIVER_ARM, Family::UNKNOWN, BUG_BROKEN_VECTOR_BITWISE_AND,
-1.0, -1.0, true},
{API_OPENGL, OS_WINDOWS, VENDOR_ATI, DRIVER_ATI, Family::UNKNOWN, BUG_BROKEN_SSBO_FIELD_ATOMICS,
-1.0, -1.0, true},
};
static std::map<Bug, BugInfo> m_bugs;

View File

@ -298,6 +298,14 @@ enum Bug
// Started version: -1
// Ended version: -1
BUG_BROKEN_VECTOR_BITWISE_AND,
// BUG: Atomic writes to different fields or array elements of an SSBO have no effect, only
// writing to the first field/element works. This causes bounding box emulation to give garbage
// values under OpenGL.
// Affected devices: AMD (Windows)
// Started version: -1
// Ended version: -1
BUG_BROKEN_SSBO_FIELD_ATOMICS,
};
// Initializes our internal vendor, device family, and driver version

View File

@ -451,20 +451,37 @@ void WritePixelShaderCommonHeader(ShaderCode& out, APIType api_type,
if (bounding_box)
{
if (api_type == APIType::D3D)
{
out.Write("globallycoherent RWBuffer<int> bbox_data : register(u2);\n"
"#define atomicMin InterlockedMin\n"
"#define atomicMax InterlockedMax");
}
else
{
out.Write("SSBO_BINDING(0) buffer BBox {{\n");
if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_SSBO_FIELD_ATOMICS))
{
// AMD drivers on Windows seemingly ignore atomic writes to fields or array elements of an
// SSBO other than the first one, but using an int4 seems to work fine
out.Write(" int4 bbox_data;\n");
}
else
{
// The Metal shader compiler fails to compile the atomic instructions when operating on
// individual components of a vector
out.Write(" int bbox_data[4];\n");
}
out.Write("}};");
}
out.Write(R"(
#ifdef API_D3D
globallycoherent RWBuffer<int> bbox_data : register(u2);
#define atomicMin InterlockedMin
#define atomicMax InterlockedMax
#define bbox_left bbox_data[0]
#define bbox_right bbox_data[1]
#define bbox_top bbox_data[2]
#define bbox_bottom bbox_data[3]
#else
SSBO_BINDING(0) buffer BBox {{
int bbox_left, bbox_right, bbox_top, bbox_bottom;
}};
#endif
void UpdateBoundingBoxBuffer(int2 min_pos, int2 max_pos) {{
if (bbox_left > min_pos.x)