Implement larger bounds for viewports and scissor rectangles in D3D11.
This fixes a bug where we would not allow the application to draw outside the viewport, which is valid.
TRAC #22497
Signed-off-by: Nicolas Capens
Signed-off-by: Shannon Woods
Author: Jamie Madill
git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1875 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index 20b5c80..b228704 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -169,6 +169,7 @@
virtual int getMajorShaderModel() const = 0;
virtual float getMaxPointSize() const = 0;
+ virtual int getMaxViewportDimension() const = 0;
virtual int getMaxTextureWidth() const = 0;
virtual int getMaxTextureHeight() const = 0;
virtual bool get32BitIndexSupport() const = 0;
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 099d931..56fa133 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -562,10 +562,10 @@
if (enabled)
{
D3D11_RECT rect;
- rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
- rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
- rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
- rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
+ rect.left = std::max(0, scissor.x);
+ rect.top = std::max(0, scissor.y);
+ rect.right = scissor.x + std::max(0, scissor.width);
+ rect.bottom = scissor.y + std::max(0, scissor.height);
mDeviceContext->RSSetScissorRects(1, &rect);
}
@@ -598,11 +598,17 @@
actualZFar = 1.0f;
}
+ // Get D3D viewport bounds, which depends on the feature level
+ const Range& viewportBounds = getViewportBounds();
+
+ // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
D3D11_VIEWPORT dxViewport;
- dxViewport.TopLeftX = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width));
- dxViewport.TopLeftY = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height));
- dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.TopLeftX));
- dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.TopLeftY));
+ dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end);
+ dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end);
+ dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension());
+ dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension());
+ dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX));
+ dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY));
dxViewport.MinDepth = actualZNear;
dxViewport.MaxDepth = actualZFar;
@@ -793,8 +799,8 @@
mRenderTargetDesc.width = renderTargetWidth;
mRenderTargetDesc.height = renderTargetHeight;
mRenderTargetDesc.format = renderTargetFormat;
- mForceSetViewport = true; // TODO: It may not be required to clamp the viewport in D3D11
- mForceSetScissor = true; // TODO: It may not be required to clamp the scissor in D3D11
+ mForceSetViewport = true;
+ mForceSetScissor = true;
if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
{
@@ -2023,6 +2029,20 @@
return true;
}
+Range Renderer11::getViewportBounds() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX);
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX);
+ default: UNREACHABLE();
+ return Range(0, 0);
+ }
+}
+
unsigned int Renderer11::getMaxVertexTextureImageUnits() const
{
META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
@@ -2160,6 +2180,21 @@
return 1024.0f;
}
+int Renderer11::getMaxViewportDimension() const
+{
+ // Clamp viewport width/height to half of the maximum right/bottom edge
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_VIEWPORT_BOUNDS_MAX - D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_VIEWPORT_BOUNDS_MAX - D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
+ default: UNREACHABLE();
+ return 0;
+ }
+}
+
int Renderer11::getMaxTextureWidth() const
{
switch (mFeatureLevel)
diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h
index 4722c8e..ed68237 100644
--- a/src/libGLESv2/renderer/Renderer11.h
+++ b/src/libGLESv2/renderer/Renderer11.h
@@ -21,6 +21,7 @@
#include "common/angleutils.h"
#include "libGLESv2/angletypes.h"
+#include "libGLESv2/mathutil.h"
#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/renderer/RenderStateCache.h"
@@ -120,6 +121,7 @@
virtual int getMajorShaderModel() const;
virtual float getMaxPointSize() const;
+ virtual int getMaxViewportDimension() const;
virtual int getMaxTextureWidth() const;
virtual int getMaxTextureHeight() const;
virtual bool get32BitIndexSupport() const;
@@ -193,6 +195,7 @@
GLint packAlignment, void *pixels);
void maskedClear(const gl::ClearParameters &clearParams);
+ rx::Range getViewportBounds() const;
bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget,
const gl::Rectangle &drawRect, BlitTarget target);
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index 7a4d31c..3846abe 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -2307,6 +2307,13 @@
return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f;
}
+int Renderer9::getMaxViewportDimension() const
+{
+ int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()),
+ (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
+ return maxTextureDimension;
+}
+
int Renderer9::getMaxTextureWidth() const
{
return (int)mDeviceCaps.MaxTextureWidth;
diff --git a/src/libGLESv2/renderer/Renderer9.h b/src/libGLESv2/renderer/Renderer9.h
index 3841208..765625c 100644
--- a/src/libGLESv2/renderer/Renderer9.h
+++ b/src/libGLESv2/renderer/Renderer9.h
@@ -149,6 +149,7 @@
virtual int getMajorShaderModel() const;
virtual float getMaxPointSize() const;
+ virtual int getMaxViewportDimension() const;
virtual int getMaxTextureWidth() const;
virtual int getMaxTextureHeight() const;
virtual bool get32BitIndexSupport() const;