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