mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-15 07:29:17 +01:00
[dxvk,d3d11,d3d9] Refactor viewport updates
Might as well use the CS chunk array functionality for this.
This commit is contained in:
parent
fed3b7cce4
commit
f37df19da2
@ -2469,8 +2469,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
// In D3D11, the rasterizer state defines whether the scissor test is
|
// In D3D11, the rasterizer state defines whether the scissor test is
|
||||||
// enabled, so if that changes, we need to update scissor rects as well.
|
// enabled, so if that changes, we need to update scissor rects as well.
|
||||||
bool currScissorEnable = currRasterizerState != nullptr ? currRasterizerState->Desc()->ScissorEnable : false;
|
bool currScissorEnable = currRasterizerState && currRasterizerState->Desc()->ScissorEnable;
|
||||||
bool nextScissorEnable = nextRasterizerState != nullptr ? nextRasterizerState->Desc()->ScissorEnable : false;
|
bool nextScissorEnable = nextRasterizerState && nextRasterizerState->Desc()->ScissorEnable;
|
||||||
|
|
||||||
if (currScissorEnable != nextScissorEnable)
|
if (currScissorEnable != nextScissorEnable)
|
||||||
ApplyViewportState();
|
ApplyViewportState();
|
||||||
@ -2545,13 +2545,8 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_state.rs.state != nullptr && dirty) {
|
if (dirty && m_state.rs.state && m_state.rs.state->Desc()->ScissorEnable)
|
||||||
D3D11_RASTERIZER_DESC rsDesc;
|
ApplyViewportState();
|
||||||
m_state.rs.state->GetDesc(&rsDesc);
|
|
||||||
|
|
||||||
if (rsDesc.ScissorEnable)
|
|
||||||
ApplyViewportState();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3487,92 +3482,52 @@ namespace dxvk {
|
|||||||
|
|
||||||
template<typename ContextType>
|
template<typename ContextType>
|
||||||
void D3D11CommonContext<ContextType>::ApplyViewportState() {
|
void D3D11CommonContext<ContextType>::ApplyViewportState() {
|
||||||
std::array<VkViewport, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> viewports;
|
|
||||||
std::array<VkRect2D, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> scissors;
|
|
||||||
|
|
||||||
// The backend can't handle a viewport count of zero,
|
|
||||||
// so we should at least specify one empty viewport
|
|
||||||
uint32_t viewportCount = m_state.rs.numViewports;
|
uint32_t viewportCount = m_state.rs.numViewports;
|
||||||
|
|
||||||
if (unlikely(!viewportCount)) {
|
if (likely(viewportCount)) {
|
||||||
viewportCount = 1;
|
EmitCsCmd<DxvkViewport>(D3D11CmdType::None, viewportCount,
|
||||||
viewports[0] = VkViewport();
|
[] (DxvkContext* ctx, const DxvkViewport* viewports, size_t count) {
|
||||||
scissors [0] = VkRect2D();
|
ctx->setViewports(count, viewports);
|
||||||
}
|
});
|
||||||
|
|
||||||
// D3D11's coordinate system has its origin in the bottom left,
|
// Vulkan does not provide an easy way to disable the scissor test,
|
||||||
// but the viewport coordinates are aligned to the top-left
|
// Set scissor rects that are at least as large as the framebuffer.
|
||||||
// corner so we can get away with flipping the viewport.
|
bool enableScissorTest = m_state.rs.state && m_state.rs.state->Desc()->ScissorEnable;
|
||||||
for (uint32_t i = 0; i < m_state.rs.numViewports; i++) {
|
|
||||||
const D3D11_VIEWPORT& vp = m_state.rs.viewports[i];
|
|
||||||
|
|
||||||
viewports[i] = VkViewport {
|
// D3D11's coordinate system has its origin in the bottom left,
|
||||||
vp.TopLeftX, vp.Height + vp.TopLeftY,
|
// but the viewport coordinates are aligned to the top-left
|
||||||
vp.Width, -vp.Height,
|
// corner so we can get away with flipping the viewport.
|
||||||
vp.MinDepth, vp.MaxDepth,
|
for (uint32_t i = 0; i < viewportCount; i++) {
|
||||||
};
|
const auto& vp = m_state.rs.viewports[i];
|
||||||
}
|
|
||||||
|
|
||||||
// Scissor rectangles. Vulkan does not provide an easy way
|
auto* dst = new (m_csData->at(i)) DxvkViewport();
|
||||||
// to disable the scissor test, so we'll have to set scissor
|
dst->viewport.x = vp.TopLeftX;
|
||||||
// rects that are at least as large as the framebuffer.
|
dst->viewport.y = vp.Height + vp.TopLeftY;
|
||||||
bool enableScissorTest = false;
|
dst->viewport.width = vp.Width;
|
||||||
|
dst->viewport.height = -vp.Height;
|
||||||
|
dst->viewport.minDepth = vp.MinDepth;
|
||||||
|
dst->viewport.maxDepth = vp.MaxDepth;
|
||||||
|
|
||||||
if (m_state.rs.state != nullptr) {
|
if (!enableScissorTest) {
|
||||||
D3D11_RASTERIZER_DESC rsDesc;
|
dst->scissor.offset = VkOffset2D { 0, 0 };
|
||||||
m_state.rs.state->GetDesc(&rsDesc);
|
dst->scissor.extent = VkExtent2D {
|
||||||
enableScissorTest = rsDesc.ScissorEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < m_state.rs.numViewports; i++) {
|
|
||||||
if (!enableScissorTest) {
|
|
||||||
scissors[i] = VkRect2D {
|
|
||||||
VkOffset2D { 0, 0 },
|
|
||||||
VkExtent2D {
|
|
||||||
D3D11_VIEWPORT_BOUNDS_MAX,
|
D3D11_VIEWPORT_BOUNDS_MAX,
|
||||||
D3D11_VIEWPORT_BOUNDS_MAX } };
|
D3D11_VIEWPORT_BOUNDS_MAX };
|
||||||
} else if (i >= m_state.rs.numScissors) {
|
} else if (i < m_state.rs.numScissors) {
|
||||||
scissors[i] = VkRect2D {
|
const auto& sr = m_state.rs.scissors[i];
|
||||||
VkOffset2D { 0, 0 },
|
|
||||||
VkExtent2D { 0, 0 } };
|
|
||||||
} else {
|
|
||||||
D3D11_RECT sr = m_state.rs.scissors[i];
|
|
||||||
|
|
||||||
VkOffset2D srPosA;
|
dst->scissor.offset = VkOffset2D { sr.left, sr.top };
|
||||||
srPosA.x = std::max<int32_t>(0, sr.left);
|
dst->scissor.extent = VkExtent2D {
|
||||||
srPosA.y = std::max<int32_t>(0, sr.top);
|
uint32_t(std::max(sr.left, sr.right) - sr.left),
|
||||||
|
uint32_t(std::max(sr.top, sr.bottom) - sr.top) };
|
||||||
VkOffset2D srPosB;
|
}
|
||||||
srPosB.x = std::max<int32_t>(srPosA.x, sr.right);
|
|
||||||
srPosB.y = std::max<int32_t>(srPosA.y, sr.bottom);
|
|
||||||
|
|
||||||
VkExtent2D srSize;
|
|
||||||
srSize.width = uint32_t(srPosB.x - srPosA.x);
|
|
||||||
srSize.height = uint32_t(srPosB.y - srPosA.y);
|
|
||||||
|
|
||||||
scissors[i] = VkRect2D { srPosA, srSize };
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (likely(viewportCount == 1)) {
|
|
||||||
EmitCs([
|
|
||||||
cViewport = viewports[0],
|
|
||||||
cScissor = scissors[0]
|
|
||||||
] (DxvkContext* ctx) {
|
|
||||||
ctx->setViewports(1,
|
|
||||||
&cViewport,
|
|
||||||
&cScissor);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
EmitCs([
|
// The backend can't handle a viewport count of zero,
|
||||||
cViewportCount = viewportCount,
|
// so we should at least specify one empty viewport
|
||||||
cViewports = viewports,
|
EmitCs([] (DxvkContext* ctx) {
|
||||||
cScissors = scissors
|
DxvkViewport viewport = { };
|
||||||
] (DxvkContext* ctx) {
|
ctx->setViewports(1, &viewport);
|
||||||
ctx->setViewports(
|
|
||||||
cViewportCount,
|
|
||||||
cViewports.data(),
|
|
||||||
cScissors.data());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4802,10 +4757,8 @@ namespace dxvk {
|
|||||||
ctx->setStencilReference(D3D11_DEFAULT_STENCIL_REFERENCE);
|
ctx->setStencilReference(D3D11_DEFAULT_STENCIL_REFERENCE);
|
||||||
|
|
||||||
// Reset viewports
|
// Reset viewports
|
||||||
auto viewport = VkViewport();
|
DxvkViewport viewport = { };
|
||||||
auto scissor = VkRect2D();
|
ctx->setViewports(1, &viewport);
|
||||||
|
|
||||||
ctx->setViewports(1, &viewport, &scissor);
|
|
||||||
|
|
||||||
// Unbind indirect draw buffer
|
// Unbind indirect draw buffer
|
||||||
ctx->bindDrawBuffers(DxvkBufferSlice(), DxvkBufferSlice());
|
ctx->bindDrawBuffers(DxvkBufferSlice(), DxvkBufferSlice());
|
||||||
|
@ -1293,8 +1293,10 @@ namespace dxvk {
|
|||||||
Rc<DxvkResourceAllocation> uboSlice = m_ubo->allocateStorage();
|
Rc<DxvkResourceAllocation> uboSlice = m_ubo->allocateStorage();
|
||||||
memcpy(uboSlice->mapPtr(), &uboData, sizeof(uboData));
|
memcpy(uboSlice->mapPtr(), &uboData, sizeof(uboData));
|
||||||
|
|
||||||
|
DxvkViewport vp = { viewport, scissor };
|
||||||
|
|
||||||
ctx->invalidateBuffer(m_ubo, std::move(uboSlice));
|
ctx->invalidateBuffer(m_ubo, std::move(uboSlice));
|
||||||
ctx->setViewports(1, &viewport, &scissor);
|
ctx->setViewports(1, &vp);
|
||||||
|
|
||||||
ctx->bindShader<VK_SHADER_STAGE_VERTEX_BIT>(Rc<DxvkShader>(m_vs));
|
ctx->bindShader<VK_SHADER_STAGE_VERTEX_BIT>(Rc<DxvkShader>(m_vs));
|
||||||
ctx->bindShader<VK_SHADER_STAGE_FRAGMENT_BIT>(Rc<DxvkShader>(m_fs));
|
ctx->bindShader<VK_SHADER_STAGE_FRAGMENT_BIT>(Rc<DxvkShader>(m_fs));
|
||||||
|
@ -6732,9 +6732,6 @@ namespace dxvk {
|
|||||||
void D3D9DeviceEx::BindViewportAndScissor() {
|
void D3D9DeviceEx::BindViewportAndScissor() {
|
||||||
m_flags.clr(D3D9DeviceFlag::DirtyViewportScissor);
|
m_flags.clr(D3D9DeviceFlag::DirtyViewportScissor);
|
||||||
|
|
||||||
VkViewport viewport;
|
|
||||||
VkRect2D scissor;
|
|
||||||
|
|
||||||
// D3D9's coordinate system has its origin in the bottom left,
|
// D3D9's coordinate system has its origin in the bottom left,
|
||||||
// but the viewport coordinates are aligned to the top-left
|
// but the viewport coordinates are aligned to the top-left
|
||||||
// corner so we can get away with flipping the viewport.
|
// corner so we can get away with flipping the viewport.
|
||||||
@ -6753,7 +6750,8 @@ namespace dxvk {
|
|||||||
zBias = 0.001f;
|
zBias = 0.001f;
|
||||||
}
|
}
|
||||||
|
|
||||||
viewport = VkViewport{
|
DxvkViewport state = { };
|
||||||
|
state.viewport = VkViewport{
|
||||||
float(vp.X) + cf, float(vp.Height + vp.Y) + cf,
|
float(vp.X) + cf, float(vp.Height + vp.Y) + cf,
|
||||||
float(vp.Width), -float(vp.Height),
|
float(vp.Width), -float(vp.Height),
|
||||||
std::clamp(vp.MinZ, 0.0f, 1.0f),
|
std::clamp(vp.MinZ, 0.0f, 1.0f),
|
||||||
@ -6784,22 +6782,18 @@ namespace dxvk {
|
|||||||
srSize.width = uint32_t(srPosB.x - srPosA.x);
|
srSize.width = uint32_t(srPosB.x - srPosA.x);
|
||||||
srSize.height = uint32_t(srPosB.y - srPosA.y);
|
srSize.height = uint32_t(srPosB.y - srPosA.y);
|
||||||
|
|
||||||
scissor = VkRect2D{ srPosA, srSize };
|
state.scissor = VkRect2D{ srPosA, srSize };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
scissor = VkRect2D{
|
state.scissor = VkRect2D{
|
||||||
VkOffset2D { int32_t(vp.X), int32_t(vp.Y) },
|
VkOffset2D { int32_t(vp.X), int32_t(vp.Y) },
|
||||||
VkExtent2D { vp.Width, vp.Height }};
|
VkExtent2D { vp.Width, vp.Height }};
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitCs([
|
EmitCs([
|
||||||
cViewport = viewport,
|
cViewport = state
|
||||||
cScissor = scissor
|
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
ctx->setViewports(
|
ctx->setViewports(1, &cViewport);
|
||||||
1,
|
|
||||||
&cViewport,
|
|
||||||
&cScissor);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2579,16 +2579,15 @@ namespace dxvk {
|
|||||||
|
|
||||||
void DxvkContext::setViewports(
|
void DxvkContext::setViewports(
|
||||||
uint32_t viewportCount,
|
uint32_t viewportCount,
|
||||||
const VkViewport* viewports,
|
const DxvkViewport* viewports) {
|
||||||
const VkRect2D* scissorRects) {
|
|
||||||
for (uint32_t i = 0; i < viewportCount; i++) {
|
for (uint32_t i = 0; i < viewportCount; i++) {
|
||||||
m_state.vp.viewports[i] = viewports[i];
|
m_state.vp.viewports[i] = viewports[i].viewport;
|
||||||
m_state.vp.scissorRects[i] = scissorRects[i];
|
m_state.vp.scissorRects[i] = viewports[i].scissor;
|
||||||
|
|
||||||
// Vulkan viewports are not allowed to have a width or
|
// Vulkan viewports are not allowed to have a width or
|
||||||
// height of zero, so we fall back to a dummy viewport
|
// height of zero, so we fall back to a dummy viewport
|
||||||
// and instead set an empty scissor rect, which is legal.
|
// and instead set an empty scissor rect, which is legal.
|
||||||
if (viewports[i].width == 0.0f || viewports[i].height == 0.0f) {
|
if (viewports[i].viewport.width <= 0.0f || viewports[i].viewport.height == 0.0f) {
|
||||||
m_state.vp.viewports[i] = VkViewport {
|
m_state.vp.viewports[i] = VkViewport {
|
||||||
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
|
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
|
||||||
m_state.vp.scissorRects[i] = VkRect2D {
|
m_state.vp.scissorRects[i] = VkRect2D {
|
||||||
|
@ -1124,13 +1124,11 @@ namespace dxvk {
|
|||||||
* \brief Sets viewports
|
* \brief Sets viewports
|
||||||
*
|
*
|
||||||
* \param [in] viewportCount Number of viewports
|
* \param [in] viewportCount Number of viewports
|
||||||
* \param [in] viewports The viewports
|
* \param [in] viewports The viewports and scissors
|
||||||
* \param [in] scissorRects Schissor rectangles
|
|
||||||
*/
|
*/
|
||||||
void setViewports(
|
void setViewports(
|
||||||
uint32_t viewportCount,
|
uint32_t viewportCount,
|
||||||
const VkViewport* viewports,
|
const DxvkViewport* viewports);
|
||||||
const VkRect2D* scissorRects);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Sets blend constants
|
* \brief Sets blend constants
|
||||||
|
@ -116,6 +116,12 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxvkViewport {
|
||||||
|
VkViewport viewport = { };
|
||||||
|
VkRect2D scissor = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct DxvkViewportState {
|
struct DxvkViewportState {
|
||||||
uint32_t viewportCount = 0;
|
uint32_t viewportCount = 0;
|
||||||
std::array<VkViewport, DxvkLimits::MaxNumViewports> viewports = { };
|
std::array<VkViewport, DxvkLimits::MaxNumViewports> viewports = { };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user