summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorConnor McLaughlin <stenzek@gmail.com>2019-03-29 19:59:25 +1000
committerGitHub <noreply@github.com>2019-03-29 19:59:25 +1000
commit154eeae8ae1e7105bc06e76dc9ff09884190867e (patch)
tree2a762e414bd8a67bd03330566c1f58686dc5a7ca /Source
parent9b6c9252e4dafe91918d91cdabc0c6e27ff9136f (diff)
parent16294acd2ae97fc7efa8e885fbfb83b834c7976d (diff)
Merge pull request #7915 from stenzek/bbox-scaled-update
VideoBackends: Scale bounding box rectangle in the pixel shader
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/VideoBackends/D3D/Render.cpp33
-rw-r--r--Source/Core/VideoBackends/OGL/Render.cpp41
-rw-r--r--Source/Core/VideoBackends/Vulkan/Renderer.cpp41
-rw-r--r--Source/Core/VideoCommon/PixelShaderGen.cpp68
-rw-r--r--Source/Core/VideoCommon/UberShaderPixel.cpp21
5 files changed, 59 insertions, 145 deletions
diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp
index a172425e3f..82f3cba743 100644
--- a/Source/Core/VideoBackends/D3D/Render.cpp
+++ b/Source/Core/VideoBackends/D3D/Render.cpp
@@ -324,40 +324,11 @@ void Renderer::UnbindTexture(const AbstractTexture* texture)
u16 Renderer::BBoxRead(int index)
{
- // Here we get the min/max value of the truncated position of the upscaled framebuffer.
- // So we have to correct them to the unscaled EFB sizes.
- int value = BBox::Get(index);
-
- if (index < 2)
- {
- // left/right
- value = value * EFB_WIDTH / m_target_width;
- }
- else
- {
- // up/down
- value = value * EFB_HEIGHT / m_target_height;
- }
- if (index & 1)
- value++; // fix max values to describe the outer border
-
- return value;
+ return static_cast<u16>(BBox::Get(index));
}
-void Renderer::BBoxWrite(int index, u16 _value)
+void Renderer::BBoxWrite(int index, u16 value)
{
- int value = _value; // u16 isn't enough to multiply by the efb width
- if (index & 1)
- value--;
- if (index < 2)
- {
- value = value * m_target_width / EFB_WIDTH;
- }
- else
- {
- value = value * m_target_height / EFB_HEIGHT;
- }
-
BBox::Set(index, value);
}
diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp
index d0f3e74c5a..fca1de7e7b 100644
--- a/Source/Core/VideoBackends/OGL/Render.cpp
+++ b/Source/Core/VideoBackends/OGL/Render.cpp
@@ -837,49 +837,30 @@ void Renderer::SetScissorRect(const MathUtil::Rectangle<int>& rc)
u16 Renderer::BBoxRead(int index)
{
- int swapped_index = index;
+ // swap 2 and 3 for top/bottom
if (index >= 2)
- swapped_index ^= 1; // swap 2 and 3 for top/bottom
+ index ^= 1;
- // Here we get the min/max value of the truncated position of the upscaled and swapped
- // framebuffer.
- // So we have to correct them to the unscaled EFB sizes.
- int value = BoundingBox::Get(swapped_index);
-
- if (index < 2)
- {
- // left/right
- value = value * EFB_WIDTH / m_target_width;
- }
- else
+ int value = BoundingBox::Get(index);
+ if (index >= 2)
{
// up/down -- we have to swap up and down
- value = value * EFB_HEIGHT / m_target_height;
- value = EFB_HEIGHT - value - 1;
+ value = EFB_HEIGHT - value;
}
- if (index & 1)
- value++; // fix max values to describe the outer border
- return value;
+ return static_cast<u16>(value);
}
-void Renderer::BBoxWrite(int index, u16 _value)
+void Renderer::BBoxWrite(int index, u16 value)
{
- int value = _value; // u16 isn't enough to multiply by the efb width
- if (index & 1)
- value--;
- if (index < 2)
- {
- value = value * m_target_width / EFB_WIDTH;
- }
- else
+ s32 swapped_value = value;
+ if (index >= 2)
{
index ^= 1; // swap 2 and 3 for top/bottom
- value = EFB_HEIGHT - value - 1;
- value = value * m_target_height / EFB_HEIGHT;
+ swapped_value = EFB_HEIGHT - swapped_value;
}
- BoundingBox::Set(index, value);
+ BoundingBox::Set(index, swapped_value);
}
void Renderer::SetViewport(float x, float y, float width, float height, float near_depth,
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
index ae3c7c5807..8b560be15d 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
@@ -131,49 +131,12 @@ void Renderer::SetPipeline(const AbstractPipeline* pipeline)
u16 Renderer::BBoxRead(int index)
{
- s32 value = m_bounding_box->Get(static_cast<size_t>(index));
-
- // Here we get the min/max value of the truncated position of the upscaled framebuffer.
- // So we have to correct them to the unscaled EFB sizes.
- if (index < 2)
- {
- // left/right
- value = value * EFB_WIDTH / m_target_width;
- }
- else
- {
- // up/down
- value = value * EFB_HEIGHT / m_target_height;
- }
-
- // fix max values to describe the outer border
- if (index & 1)
- value++;
-
- return static_cast<u16>(value);
+ return static_cast<u16>(m_bounding_box->Get(index));
}
void Renderer::BBoxWrite(int index, u16 value)
{
- s32 scaled_value = static_cast<s32>(value);
-
- // fix max values to describe the outer border
- if (index & 1)
- scaled_value--;
-
- // scale to internal resolution
- if (index < 2)
- {
- // left/right
- scaled_value = scaled_value * m_target_width / EFB_WIDTH;
- }
- else
- {
- // up/down
- scaled_value = scaled_value * m_target_height / EFB_HEIGHT;
- }
-
- m_bounding_box->Set(static_cast<size_t>(index), scaled_value);
+ m_bounding_box->Set(index, value);
}
void Renderer::BBoxFlush()
diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp
index 9936bcb85c..4d37418725 100644
--- a/Source/Core/VideoCommon/PixelShaderGen.cpp
+++ b/Source/Core/VideoCommon/PixelShaderGen.cpp
@@ -444,16 +444,46 @@ void WritePixelShaderCommonHeader(ShaderCode& out, APIType ApiType, u32 num_texg
if (bounding_box)
{
- if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
- {
- out.Write("SSBO_BINDING(0) buffer BBox {\n"
- "\tint bbox_left, bbox_right, bbox_top, bbox_bottom;\n"
- "};\n");
- }
- else
- {
- out.Write("globallycoherent RWBuffer<int> bbox_data : register(u2);\n");
- }
+ 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 UpdateBoundingBox(float2 rawpos) {
+ // The pixel center in the GameCube GPU is 7/12, not 0.5 (see VertexShaderGen.cpp)
+ // Adjust for this by unapplying the offset we added in the vertex shader.
+ const float PIXEL_CENTER_OFFSET = 7.0 / 12.0 - 0.5;
+ float2 offset = float2(PIXEL_CENTER_OFFSET, -PIXEL_CENTER_OFFSET);
+
+#ifdef API_OPENGL
+ // OpenGL lower-left origin means that Y goes in the opposite direction.
+ offset.y = -offset.y;
+#endif
+
+ // The bounding box register is exclusive of the right coordinate, hence the +1.
+ int2 pos = iround(rawpos * cefbscale + offset);
+ int2 pos_offset = pos + int2(1, 1);
+
+ if (bbox_left > pos.x)
+ atomicMin(bbox_left, pos.x);
+ if (bbox_right < pos_offset.x)
+ atomicMax(bbox_right, pos_offset.x);
+ if (bbox_top > pos.y)
+ atomicMin(bbox_top, pos.y);
+ if (bbox_bottom < pos_offset.y)
+ atomicMax(bbox_bottom, pos_offset.y);
+}
+)");
}
}
@@ -859,23 +889,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host
WriteBlend(out, uid_data);
if (uid_data->bounding_box)
- {
- if (ApiType == APIType::D3D)
- {
- out.Write(
- "\tif(bbox_data[0] > int(rawpos.x)) InterlockedMin(bbox_data[0], int(rawpos.x));\n"
- "\tif(bbox_data[1] < int(rawpos.x)) InterlockedMax(bbox_data[1], int(rawpos.x));\n"
- "\tif(bbox_data[2] > int(rawpos.y)) InterlockedMin(bbox_data[2], int(rawpos.y));\n"
- "\tif(bbox_data[3] < int(rawpos.y)) InterlockedMax(bbox_data[3], int(rawpos.y));\n");
- }
- else
- {
- out.Write("\tif(bbox_left > int(rawpos.x)) atomicMin(bbox_left, int(rawpos.x));\n"
- "\tif(bbox_right < int(rawpos.x)) atomicMax(bbox_right, int(rawpos.x));\n"
- "\tif(bbox_top > int(rawpos.y)) atomicMin(bbox_top, int(rawpos.y));\n"
- "\tif(bbox_bottom < int(rawpos.y)) atomicMax(bbox_bottom, int(rawpos.y));\n");
- }
- }
+ out.Write("\tUpdateBoundingBox(rawpos.xy);\n");
out.Write("}\n");
diff --git a/Source/Core/VideoCommon/UberShaderPixel.cpp b/Source/Core/VideoCommon/UberShaderPixel.cpp
index 1b9695f5ce..097b6456bd 100644
--- a/Source/Core/VideoCommon/UberShaderPixel.cpp
+++ b/Source/Core/VideoCommon/UberShaderPixel.cpp
@@ -1250,24 +1250,9 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
if (bounding_box)
{
- out.Write(" if (bpmem_bounding_box) {\n");
- if (ApiType == APIType::D3D)
- {
- out.Write(
- " if(bbox_data[0] > int(rawpos.x)) InterlockedMin(bbox_data[0], int(rawpos.x));\n"
- " if(bbox_data[1] < int(rawpos.x)) InterlockedMax(bbox_data[1], int(rawpos.x));\n"
- " if(bbox_data[2] > int(rawpos.y)) InterlockedMin(bbox_data[2], int(rawpos.y));\n"
- " if(bbox_data[3] < int(rawpos.y)) InterlockedMax(bbox_data[3], int(rawpos.y));\n");
- }
- else
- {
- out.Write("\tif(bbox_left > int(rawpos.x)) atomicMin(bbox_left, int(rawpos.x));\n"
- "\tif(bbox_right < int(rawpos.x)) atomicMax(bbox_right, int(rawpos.x));\n"
- "\tif(bbox_top > int(rawpos.y)) atomicMin(bbox_top, int(rawpos.y));\n"
- "\tif(bbox_bottom < int(rawpos.y)) atomicMax(bbox_bottom, int(rawpos.y));\n");
- }
-
- out.Write(" }\n");
+ out.Write(" if (bpmem_bounding_box) {\n"
+ " UpdateBoundingBox(rawpos.xy);\n"
+ " }\n");
}
if (use_shader_blend)