feat: support rect clears for camera viewport rendering
This commit is contained in:
@@ -102,10 +102,19 @@ public:
|
||||
void DrawIndexedInstancedIndirectInternal(ID3D12Resource* argBuffer, uint64_t alignedByteOffset);
|
||||
|
||||
void Clear(float r, float g, float b, float a, uint32_t buffers) override;
|
||||
void ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) override;
|
||||
void ClearRenderTarget(
|
||||
RHIResourceView* renderTarget,
|
||||
const float color[4],
|
||||
uint32_t rectCount = 0,
|
||||
const Rect* rects = nullptr) override;
|
||||
void ClearRenderTargetView(ID3D12Resource* renderTarget, const float color[4], uint32_t rectCount = 0, const D3D12_RECT* rects = nullptr);
|
||||
void ClearRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE renderTargetHandle, const float color[4], uint32_t rectCount = 0, const D3D12_RECT* rects = nullptr);
|
||||
void ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) override;
|
||||
void ClearDepthStencil(
|
||||
RHIResourceView* depthStencil,
|
||||
float depth,
|
||||
uint8_t stencil,
|
||||
uint32_t rectCount = 0,
|
||||
const Rect* rects = nullptr) override;
|
||||
void ClearDepthStencilView(ID3D12Resource* depthStencil, uint32_t clearFlags, float depth = 1.0f, uint8_t stencil = 0, uint32_t rectCount = 0, const D3D12_RECT* rects = nullptr);
|
||||
void ClearDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE depthStencilHandle, uint32_t clearFlags, float depth = 1.0f, uint8_t stencil = 0, uint32_t rectCount = 0, const D3D12_RECT* rects = nullptr);
|
||||
void ClearUnorderedAccessView(D3D12_GPU_DESCRIPTOR_HANDLE viewHandle, D3D12_CPU_DESCRIPTOR_HANDLE resourceHandle, ID3D12Resource* unorderedAccess, const float values[4], uint32_t rectCount = 0, const D3D12_RECT* rects = nullptr);
|
||||
@@ -154,4 +163,4 @@ private:
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
} // namespace XCEngine
|
||||
|
||||
@@ -192,8 +192,17 @@ public:
|
||||
void SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, RHIResourceView* depthStencil = nullptr) override;
|
||||
void SetStencilRef(uint8_t ref) override;
|
||||
void SetBlendFactor(const float factor[4]) override;
|
||||
void ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) override;
|
||||
void ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) override;
|
||||
void ClearRenderTarget(
|
||||
RHIResourceView* renderTarget,
|
||||
const float color[4],
|
||||
uint32_t rectCount = 0,
|
||||
const Rect* rects = nullptr) override;
|
||||
void ClearDepthStencil(
|
||||
RHIResourceView* depthStencil,
|
||||
float depth,
|
||||
uint8_t stencil,
|
||||
uint32_t rectCount = 0,
|
||||
const Rect* rects = nullptr) override;
|
||||
void Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) override;
|
||||
void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) override;
|
||||
|
||||
@@ -212,6 +221,8 @@ private:
|
||||
std::vector<unsigned int> m_enabledVertexAttributes;
|
||||
OpenGLShader* m_currentShader;
|
||||
OpenGLFramebuffer* m_composedFramebuffer;
|
||||
uint32_t m_currentRenderTargetWidth;
|
||||
uint32_t m_currentRenderTargetHeight;
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
|
||||
@@ -92,8 +92,17 @@ public:
|
||||
virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount = 1, uint32_t startIndex = 0, int32_t baseVertex = 0, uint32_t startInstance = 0) = 0;
|
||||
|
||||
virtual void Clear(float r, float g, float b, float a, uint32_t buffers) = 0;
|
||||
virtual void ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) = 0;
|
||||
virtual void ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) = 0;
|
||||
virtual void ClearRenderTarget(
|
||||
RHIResourceView* renderTarget,
|
||||
const float color[4],
|
||||
uint32_t rectCount = 0,
|
||||
const Rect* rects = nullptr) = 0;
|
||||
virtual void ClearDepthStencil(
|
||||
RHIResourceView* depthStencil,
|
||||
float depth,
|
||||
uint8_t stencil,
|
||||
uint32_t rectCount = 0,
|
||||
const Rect* rects = nullptr) = 0;
|
||||
|
||||
virtual void CopyResource(RHIResourceView* dst, RHIResourceView* src) = 0;
|
||||
|
||||
|
||||
@@ -52,8 +52,17 @@ public:
|
||||
void DrawIndexed(uint32_t indexCount, uint32_t instanceCount = 1, uint32_t startIndex = 0, int32_t baseVertex = 0, uint32_t startInstance = 0) override;
|
||||
|
||||
void Clear(float r, float g, float b, float a, uint32_t buffers) override;
|
||||
void ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) override;
|
||||
void ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) override;
|
||||
void ClearRenderTarget(
|
||||
RHIResourceView* renderTarget,
|
||||
const float color[4],
|
||||
uint32_t rectCount = 0,
|
||||
const Rect* rects = nullptr) override;
|
||||
void ClearDepthStencil(
|
||||
RHIResourceView* depthStencil,
|
||||
float depth,
|
||||
uint8_t stencil,
|
||||
uint32_t rectCount = 0,
|
||||
const Rect* rects = nullptr) override;
|
||||
|
||||
void CopyResource(RHIResourceView* dst, RHIResourceView* src) override;
|
||||
void Dispatch(uint32_t x, uint32_t y, uint32_t z) override;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
@@ -765,16 +766,54 @@ void D3D12CommandList::Clear(float r, float g, float b, float a, uint32_t buffer
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12CommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) {
|
||||
void D3D12CommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4], uint32_t rectCount, const Rect* rects) {
|
||||
if (!renderTarget || !renderTarget->IsValid()) return;
|
||||
|
||||
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(renderTarget);
|
||||
ClearRenderTargetView(view->GetCPUHandle(), color, 0, nullptr);
|
||||
std::vector<D3D12_RECT> nativeRects;
|
||||
const D3D12_RECT* nativeRectData = nullptr;
|
||||
if (rectCount > 0 && rects != nullptr) {
|
||||
nativeRects.reserve(rectCount);
|
||||
for (uint32_t i = 0; i < rectCount; ++i) {
|
||||
nativeRects.push_back(D3D12_RECT{
|
||||
rects[i].left,
|
||||
rects[i].top,
|
||||
rects[i].right,
|
||||
rects[i].bottom
|
||||
});
|
||||
}
|
||||
nativeRectData = nativeRects.data();
|
||||
}
|
||||
|
||||
ClearRenderTargetView(view->GetCPUHandle(), color, static_cast<uint32_t>(nativeRects.size()), nativeRectData);
|
||||
}
|
||||
|
||||
void D3D12CommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) {
|
||||
void D3D12CommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil, uint32_t rectCount, const Rect* rects) {
|
||||
if (!depthStencil || !depthStencil->IsValid()) return;
|
||||
|
||||
D3D12ResourceView* view = static_cast<D3D12ResourceView*>(depthStencil);
|
||||
ClearDepthStencilView(view->GetCPUHandle(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, depth, stencil, 0, nullptr);
|
||||
std::vector<D3D12_RECT> nativeRects;
|
||||
const D3D12_RECT* nativeRectData = nullptr;
|
||||
if (rectCount > 0 && rects != nullptr) {
|
||||
nativeRects.reserve(rectCount);
|
||||
for (uint32_t i = 0; i < rectCount; ++i) {
|
||||
nativeRects.push_back(D3D12_RECT{
|
||||
rects[i].left,
|
||||
rects[i].top,
|
||||
rects[i].right,
|
||||
rects[i].bottom
|
||||
});
|
||||
}
|
||||
nativeRectData = nativeRects.data();
|
||||
}
|
||||
|
||||
ClearDepthStencilView(
|
||||
view->GetCPUHandle(),
|
||||
D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL,
|
||||
depth,
|
||||
stencil,
|
||||
static_cast<uint32_t>(nativeRects.size()),
|
||||
nativeRectData);
|
||||
}
|
||||
|
||||
void D3D12CommandList::ClearDepthStencilView(ID3D12Resource* depthStencil, uint32_t clearFlags, float depth, uint8_t stencil, uint32_t rectCount, const D3D12_RECT* rects) {
|
||||
|
||||
@@ -27,6 +27,41 @@ struct OpenGLVertexAttribFormat {
|
||||
bool integer = false;
|
||||
};
|
||||
|
||||
bool ClampOpenGLClearRect(const Rect& rect, GLsizei width, GLsizei height, GLint& x, GLint& y, GLsizei& outWidth, GLsizei& outHeight) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const GLint left = std::clamp(rect.left, 0, static_cast<int32_t>(width));
|
||||
const GLint right = std::clamp(rect.right, 0, static_cast<int32_t>(width));
|
||||
const GLint top = std::clamp(rect.top, 0, static_cast<int32_t>(height));
|
||||
const GLint bottom = std::clamp(rect.bottom, 0, static_cast<int32_t>(height));
|
||||
if (right <= left || bottom <= top) {
|
||||
return false;
|
||||
}
|
||||
|
||||
x = left;
|
||||
y = static_cast<GLint>(height) - bottom;
|
||||
outWidth = right - left;
|
||||
outHeight = bottom - top;
|
||||
return outWidth > 0 && outHeight > 0;
|
||||
}
|
||||
|
||||
bool GetOpenGLClearTargetExtent(const OpenGLResourceView* view, GLsizei& width, GLsizei& height) {
|
||||
if (view == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const OpenGLTexture* texture = view->GetTextureResource();
|
||||
if (texture == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
width = static_cast<GLsizei>(texture->GetWidth());
|
||||
height = static_cast<GLsizei>(texture->GetHeight());
|
||||
return width > 0 && height > 0;
|
||||
}
|
||||
|
||||
bool GetOpenGLVertexAttribFormat(Format format, OpenGLVertexAttribFormat& attributeFormat) {
|
||||
switch (format) {
|
||||
case Format::R8_UNorm:
|
||||
@@ -50,6 +85,9 @@ bool GetOpenGLVertexAttribFormat(Format format, OpenGLVertexAttribFormat& attrib
|
||||
case Format::R32G32_Float:
|
||||
attributeFormat = { 2, GL_FLOAT, GL_FALSE, false };
|
||||
return true;
|
||||
case Format::R32G32B32_Float:
|
||||
attributeFormat = { 3, GL_FLOAT, GL_FALSE, false };
|
||||
return true;
|
||||
case Format::R32G32B32A32_Float:
|
||||
attributeFormat = { 4, GL_FLOAT, GL_FALSE, false };
|
||||
return true;
|
||||
@@ -99,7 +137,9 @@ OpenGLCommandList::OpenGLCommandList()
|
||||
, m_currentIndexOffset(0)
|
||||
, m_currentPipelineState(nullptr)
|
||||
, m_currentShader(nullptr)
|
||||
, m_composedFramebuffer(nullptr) {
|
||||
, m_composedFramebuffer(nullptr)
|
||||
, m_currentRenderTargetWidth(0)
|
||||
, m_currentRenderTargetHeight(0) {
|
||||
}
|
||||
|
||||
OpenGLCommandList::~OpenGLCommandList() {
|
||||
@@ -510,6 +550,8 @@ void OpenGLCommandList::Shutdown() {
|
||||
}
|
||||
m_currentPipelineState = nullptr;
|
||||
m_currentShader = nullptr;
|
||||
m_currentRenderTargetWidth = 0;
|
||||
m_currentRenderTargetHeight = 0;
|
||||
}
|
||||
|
||||
void OpenGLCommandList::Reset() {
|
||||
@@ -517,6 +559,8 @@ void OpenGLCommandList::Reset() {
|
||||
m_currentPipelineState = nullptr;
|
||||
m_currentIndexOffset = 0;
|
||||
m_currentIndexType = GL_UNSIGNED_INT;
|
||||
m_currentRenderTargetWidth = 0;
|
||||
m_currentRenderTargetHeight = 0;
|
||||
}
|
||||
|
||||
void OpenGLCommandList::Close() {
|
||||
@@ -589,6 +633,8 @@ void OpenGLCommandList::BeginRenderPass(RHIRenderPass* renderPass, RHIFramebuffe
|
||||
|
||||
OpenGLFramebuffer* glFramebuffer = static_cast<OpenGLFramebuffer*>(framebuffer);
|
||||
glFramebuffer->Bind();
|
||||
m_currentRenderTargetWidth = glFramebuffer->GetWidth();
|
||||
m_currentRenderTargetHeight = glFramebuffer->GetHeight();
|
||||
|
||||
if (!renderPass) return;
|
||||
|
||||
@@ -621,15 +667,23 @@ void OpenGLCommandList::EndRenderPass() {
|
||||
}
|
||||
|
||||
void OpenGLCommandList::SetViewport(const Viewport& viewport) {
|
||||
glViewport(static_cast<int>(viewport.topLeftX), static_cast<int>(viewport.topLeftY),
|
||||
static_cast<int>(viewport.width), static_cast<int>(viewport.height));
|
||||
const int width = static_cast<int>(viewport.width);
|
||||
const int height = static_cast<int>(viewport.height);
|
||||
const int x = static_cast<int>(viewport.topLeftX);
|
||||
int y = static_cast<int>(viewport.topLeftY);
|
||||
if (m_currentRenderTargetHeight > 0) {
|
||||
y = static_cast<int>(m_currentRenderTargetHeight) - (y + height);
|
||||
}
|
||||
glViewport(x, y, width, height);
|
||||
}
|
||||
|
||||
void OpenGLCommandList::SetViewports(uint32_t count, const Viewport* viewports) {
|
||||
std::vector<float> viewportsGL(count * 6);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
viewportsGL[i * 6 + 0] = viewports[i].topLeftX;
|
||||
viewportsGL[i * 6 + 1] = viewports[i].topLeftY;
|
||||
viewportsGL[i * 6 + 1] = m_currentRenderTargetHeight > 0
|
||||
? static_cast<float>(m_currentRenderTargetHeight) - (viewports[i].topLeftY + viewports[i].height)
|
||||
: viewports[i].topLeftY;
|
||||
viewportsGL[i * 6 + 2] = viewports[i].width;
|
||||
viewportsGL[i * 6 + 3] = viewports[i].height;
|
||||
viewportsGL[i * 6 + 4] = viewports[i].minDepth;
|
||||
@@ -639,14 +693,22 @@ void OpenGLCommandList::SetViewports(uint32_t count, const Viewport* viewports)
|
||||
}
|
||||
|
||||
void OpenGLCommandList::SetScissorRect(const Rect& rect) {
|
||||
glScissor(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
|
||||
const int width = rect.right - rect.left;
|
||||
const int height = rect.bottom - rect.top;
|
||||
int y = rect.top;
|
||||
if (m_currentRenderTargetHeight > 0) {
|
||||
y = static_cast<int>(m_currentRenderTargetHeight) - rect.bottom;
|
||||
}
|
||||
glScissor(rect.left, y, width, height);
|
||||
}
|
||||
|
||||
void OpenGLCommandList::SetScissorRects(uint32_t count, const Rect* rects) {
|
||||
std::vector<int> scissorGL(count * 4);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
scissorGL[i * 4 + 0] = rects[i].left;
|
||||
scissorGL[i * 4 + 1] = rects[i].top;
|
||||
scissorGL[i * 4 + 1] = m_currentRenderTargetHeight > 0
|
||||
? static_cast<int>(m_currentRenderTargetHeight) - rects[i].bottom
|
||||
: rects[i].top;
|
||||
scissorGL[i * 4 + 2] = rects[i].right - rects[i].left;
|
||||
scissorGL[i * 4 + 3] = rects[i].bottom - rects[i].top;
|
||||
}
|
||||
@@ -654,6 +716,9 @@ void OpenGLCommandList::SetScissorRects(uint32_t count, const Rect* rects) {
|
||||
}
|
||||
|
||||
void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, RHIResourceView* depthStencil) {
|
||||
m_currentRenderTargetWidth = 0;
|
||||
m_currentRenderTargetHeight = 0;
|
||||
|
||||
if (count > 0 && renderTargets != nullptr) {
|
||||
const bool requiresComposedFramebuffer = count > 1 || depthStencil != nullptr;
|
||||
std::vector<GLenum> drawBuffers(count, GL_NONE);
|
||||
@@ -696,9 +761,16 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** rende
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_composedFramebuffer->GetFramebuffer());
|
||||
m_currentRenderTargetWidth = width;
|
||||
m_currentRenderTargetHeight = height;
|
||||
} else {
|
||||
ReleaseComposedFramebuffer();
|
||||
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTargets[0]);
|
||||
const OpenGLTexture* texture = view != nullptr ? view->GetTextureResource() : nullptr;
|
||||
if (texture != nullptr) {
|
||||
m_currentRenderTargetWidth = texture->GetWidth();
|
||||
m_currentRenderTargetHeight = texture->GetHeight();
|
||||
}
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view != nullptr ? view->GetFramebuffer() : 0);
|
||||
}
|
||||
|
||||
@@ -707,6 +779,11 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** rende
|
||||
ReleaseComposedFramebuffer();
|
||||
OpenGLResourceView* dsv = static_cast<OpenGLResourceView*>(depthStencil);
|
||||
if (dsv && dsv->IsValid()) {
|
||||
const OpenGLTexture* depthTexture = dsv->GetTextureResource();
|
||||
if (depthTexture != nullptr) {
|
||||
m_currentRenderTargetWidth = depthTexture->GetWidth();
|
||||
m_currentRenderTargetHeight = depthTexture->GetHeight();
|
||||
}
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dsv->GetFramebuffer());
|
||||
}
|
||||
glDrawBuffers(0, nullptr);
|
||||
@@ -718,35 +795,114 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** rende
|
||||
(void)depthStencil;
|
||||
}
|
||||
|
||||
void OpenGLCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) {
|
||||
void OpenGLCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4], uint32_t rectCount, const Rect* rects) {
|
||||
if (!renderTarget) return;
|
||||
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTarget);
|
||||
if (!view->IsValid()) return;
|
||||
|
||||
GLuint prevFBO = 0;
|
||||
GLint prevScissorBox[4] = {};
|
||||
GLboolean prevScissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
|
||||
GLboolean prevColorMask[4] = {};
|
||||
GLfloat prevClearColor[4] = {};
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, reinterpret_cast<GLint*>(&prevFBO));
|
||||
glGetIntegerv(GL_SCISSOR_BOX, prevScissorBox);
|
||||
glGetBooleanv(GL_COLOR_WRITEMASK, prevColorMask);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, prevClearColor);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view->GetFramebuffer());
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glClearColor(color[0], color[1], color[2], color[3]);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
GLsizei framebufferWidth = 0;
|
||||
GLsizei framebufferHeight = 0;
|
||||
if (rectCount > 0 && rects != nullptr && GetOpenGLClearTargetExtent(view, framebufferWidth, framebufferHeight)) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
for (uint32_t i = 0; i < rectCount; ++i) {
|
||||
GLint x = 0;
|
||||
GLint y = 0;
|
||||
GLsizei width = 0;
|
||||
GLsizei height = 0;
|
||||
if (!ClampOpenGLClearRect(rects[i], framebufferWidth, framebufferHeight, x, y, width, height)) {
|
||||
continue;
|
||||
}
|
||||
glScissor(x, y, width, height);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
} else {
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFBO);
|
||||
glClearColor(prevClearColor[0], prevClearColor[1], prevClearColor[2], prevClearColor[3]);
|
||||
glColorMask(prevColorMask[0], prevColorMask[1], prevColorMask[2], prevColorMask[3]);
|
||||
glScissor(prevScissorBox[0], prevScissorBox[1], prevScissorBox[2], prevScissorBox[3]);
|
||||
if (prevScissorEnabled == GL_TRUE) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) {
|
||||
void OpenGLCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil, uint32_t rectCount, const Rect* rects) {
|
||||
if (!depthStencil) return;
|
||||
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(depthStencil);
|
||||
if (!view->IsValid()) return;
|
||||
|
||||
GLuint prevFBO = 0;
|
||||
GLint prevScissorBox[4] = {};
|
||||
GLint prevStencilMaskFront = 0;
|
||||
GLint prevStencilMaskBack = 0;
|
||||
GLint prevStencilClear = 0;
|
||||
GLboolean prevScissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
|
||||
GLboolean prevDepthMask = GL_TRUE;
|
||||
GLdouble prevDepthClear = 1.0;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, reinterpret_cast<GLint*>(&prevFBO));
|
||||
glGetIntegerv(GL_SCISSOR_BOX, prevScissorBox);
|
||||
glGetBooleanv(GL_DEPTH_WRITEMASK, &prevDepthMask);
|
||||
glGetDoublev(GL_DEPTH_CLEAR_VALUE, &prevDepthClear);
|
||||
glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &prevStencilClear);
|
||||
glGetIntegerv(GL_STENCIL_WRITEMASK, &prevStencilMaskFront);
|
||||
glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &prevStencilMaskBack);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, view->GetFramebuffer());
|
||||
glDepthMask(GL_TRUE);
|
||||
glStencilMaskSeparate(GL_FRONT, 0xFF);
|
||||
glStencilMaskSeparate(GL_BACK, 0xFF);
|
||||
glClearDepth(depth);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
glClearStencil(stencil);
|
||||
|
||||
GLsizei framebufferWidth = 0;
|
||||
GLsizei framebufferHeight = 0;
|
||||
if (rectCount > 0 && rects != nullptr && GetOpenGLClearTargetExtent(view, framebufferWidth, framebufferHeight)) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
for (uint32_t i = 0; i < rectCount; ++i) {
|
||||
GLint x = 0;
|
||||
GLint y = 0;
|
||||
GLsizei width = 0;
|
||||
GLsizei height = 0;
|
||||
if (!ClampOpenGLClearRect(rects[i], framebufferWidth, framebufferHeight, x, y, width, height)) {
|
||||
continue;
|
||||
}
|
||||
glScissor(x, y, width, height);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
} else {
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFBO);
|
||||
(void)stencil;
|
||||
glClearDepth(prevDepthClear);
|
||||
glClearStencil(prevStencilClear);
|
||||
glDepthMask(prevDepthMask);
|
||||
glStencilMaskSeparate(GL_FRONT, static_cast<GLuint>(prevStencilMaskFront));
|
||||
glStencilMaskSeparate(GL_BACK, static_cast<GLuint>(prevStencilMaskBack));
|
||||
glScissor(prevScissorBox[0], prevScissorBox[1], prevScissorBox[2], prevScissorBox[3]);
|
||||
if (prevScissorEnabled == GL_TRUE) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLCommandList::SetPipelineState(RHIPipelineState* pipelineState) {
|
||||
|
||||
@@ -125,6 +125,92 @@ ResourceStates ResolvePostCopyState(ResourceStates previousState, ResourceStates
|
||||
return previousState == ResourceStates::Common ? fallbackState : previousState;
|
||||
}
|
||||
|
||||
bool ClampVulkanClearRect(const Rect& rect, uint32_t width, uint32_t height, VkClearRect& clearRect) {
|
||||
const int32_t clampedLeft = std::clamp(rect.left, 0, static_cast<int32_t>(width));
|
||||
const int32_t clampedTop = std::clamp(rect.top, 0, static_cast<int32_t>(height));
|
||||
const int32_t clampedRight = std::clamp(rect.right, 0, static_cast<int32_t>(width));
|
||||
const int32_t clampedBottom = std::clamp(rect.bottom, 0, static_cast<int32_t>(height));
|
||||
if (clampedRight <= clampedLeft || clampedBottom <= clampedTop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
clearRect.baseArrayLayer = 0;
|
||||
clearRect.layerCount = 1;
|
||||
clearRect.rect.offset = { clampedLeft, clampedTop };
|
||||
clearRect.rect.extent = {
|
||||
static_cast<uint32_t>(clampedRight - clampedLeft),
|
||||
static_cast<uint32_t>(clampedBottom - clampedTop)
|
||||
};
|
||||
return clearRect.rect.extent.width > 0 && clearRect.rect.extent.height > 0;
|
||||
}
|
||||
|
||||
VkRenderPass CreateTransientClearRenderPass(
|
||||
VkDevice device,
|
||||
bool hasColorAttachment,
|
||||
Format colorFormat,
|
||||
bool hasDepthAttachment,
|
||||
Format depthFormat) {
|
||||
std::vector<VkAttachmentDescription> attachments;
|
||||
attachments.reserve((hasColorAttachment ? 1u : 0u) + (hasDepthAttachment ? 1u : 0u));
|
||||
|
||||
VkAttachmentReference colorAttachmentRef = {};
|
||||
if (hasColorAttachment) {
|
||||
VkAttachmentDescription colorAttachment = {};
|
||||
colorAttachment.format = ToVulkanFormat(colorFormat);
|
||||
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachments.push_back(colorAttachment);
|
||||
|
||||
colorAttachmentRef.attachment = 0;
|
||||
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
|
||||
VkAttachmentReference depthAttachmentRef = {};
|
||||
if (hasDepthAttachment) {
|
||||
VkAttachmentDescription depthAttachment = {};
|
||||
depthAttachment.format = ToVulkanFormat(depthFormat);
|
||||
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
attachments.push_back(depthAttachment);
|
||||
|
||||
depthAttachmentRef.attachment = hasColorAttachment ? 1u : 0u;
|
||||
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
|
||||
VkSubpassDescription subpass = {};
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
if (hasColorAttachment) {
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &colorAttachmentRef;
|
||||
}
|
||||
if (hasDepthAttachment) {
|
||||
subpass.pDepthStencilAttachment = &depthAttachmentRef;
|
||||
}
|
||||
|
||||
VkRenderPassCreateInfo renderPassInfo = {};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
||||
renderPassInfo.pAttachments = attachments.data();
|
||||
renderPassInfo.subpassCount = 1;
|
||||
renderPassInfo.pSubpasses = &subpass;
|
||||
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
return renderPass;
|
||||
}
|
||||
|
||||
void TransitionBuffer(VkCommandBuffer commandBuffer, VulkanBuffer* buffer, ResourceStates newState) {
|
||||
if (commandBuffer == VK_NULL_HANDLE || buffer == nullptr || buffer->GetBuffer() == VK_NULL_HANDLE) {
|
||||
return;
|
||||
@@ -637,42 +723,191 @@ void VulkanCommandList::Clear(float r, float g, float b, float a, uint32_t buffe
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) {
|
||||
void VulkanCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4], uint32_t rectCount, const Rect* rects) {
|
||||
m_currentColorTarget = renderTarget;
|
||||
Clear(color[0], color[1], color[2], color[3], 1);
|
||||
|
||||
auto* colorView = static_cast<VulkanResourceView*>(renderTarget);
|
||||
if (rectCount == 0 || rects == nullptr || colorView == nullptr || colorView->GetTexture() == nullptr) {
|
||||
Clear(color[0], color[1], color[2], color[3], 1);
|
||||
return;
|
||||
}
|
||||
|
||||
EndActiveRenderPass();
|
||||
|
||||
VulkanTexture* colorTexture = colorView->GetTexture();
|
||||
TransitionTexture(colorTexture, ResourceStates::RenderTarget);
|
||||
|
||||
std::vector<VkClearRect> clearRects;
|
||||
clearRects.reserve(rectCount);
|
||||
for (uint32_t i = 0; i < rectCount; ++i) {
|
||||
VkClearRect clearRect = {};
|
||||
if (ClampVulkanClearRect(rects[i], colorTexture->GetWidth(), colorTexture->GetHeight(), clearRect)) {
|
||||
clearRects.push_back(clearRect);
|
||||
}
|
||||
}
|
||||
if (clearRects.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
VkRenderPass renderPass = CreateTransientClearRenderPass(
|
||||
m_device->GetDevice(),
|
||||
true,
|
||||
colorTexture->GetFormat(),
|
||||
false,
|
||||
Format::Unknown);
|
||||
if (renderPass == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const VkImageView attachments[] = { colorView->GetImageView() };
|
||||
VkFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebufferInfo.renderPass = renderPass;
|
||||
framebufferInfo.attachmentCount = 1;
|
||||
framebufferInfo.pAttachments = attachments;
|
||||
framebufferInfo.width = colorTexture->GetWidth();
|
||||
framebufferInfo.height = colorTexture->GetHeight();
|
||||
framebufferInfo.layers = 1;
|
||||
|
||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||
if (vkCreateFramebuffer(m_device->GetDevice(), &framebufferInfo, nullptr, &framebuffer) != VK_SUCCESS) {
|
||||
vkDestroyRenderPass(m_device->GetDevice(), renderPass, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
VkRenderPassBeginInfo beginInfo = {};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
beginInfo.renderPass = renderPass;
|
||||
beginInfo.framebuffer = framebuffer;
|
||||
beginInfo.renderArea.offset = { 0, 0 };
|
||||
beginInfo.renderArea.extent = { colorTexture->GetWidth(), colorTexture->GetHeight() };
|
||||
beginInfo.clearValueCount = 0;
|
||||
beginInfo.pClearValues = nullptr;
|
||||
|
||||
vkCmdBeginRenderPass(m_commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
VkClearAttachment attachment = {};
|
||||
attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
attachment.colorAttachment = 0;
|
||||
attachment.clearValue.color.float32[0] = color[0];
|
||||
attachment.clearValue.color.float32[1] = color[1];
|
||||
attachment.clearValue.color.float32[2] = color[2];
|
||||
attachment.clearValue.color.float32[3] = color[3];
|
||||
vkCmdClearAttachments(
|
||||
m_commandBuffer,
|
||||
1,
|
||||
&attachment,
|
||||
static_cast<uint32_t>(clearRects.size()),
|
||||
clearRects.data());
|
||||
|
||||
vkCmdEndRenderPass(m_commandBuffer);
|
||||
vkDestroyFramebuffer(m_device->GetDevice(), framebuffer, nullptr);
|
||||
vkDestroyRenderPass(m_device->GetDevice(), renderPass, nullptr);
|
||||
}
|
||||
|
||||
void VulkanCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) {
|
||||
void VulkanCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil, uint32_t rectCount, const Rect* rects) {
|
||||
auto* depthView = static_cast<VulkanResourceView*>(depthStencil != nullptr ? depthStencil : m_currentDepthTarget);
|
||||
if (depthView == nullptr || depthView->GetTexture() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rectCount == 0 || rects == nullptr) {
|
||||
EndActiveRenderPass();
|
||||
|
||||
VulkanTexture* texture = depthView->GetTexture();
|
||||
TransitionTexture(texture, ResourceStates::CopyDst);
|
||||
|
||||
VkClearDepthStencilValue clearValue = {};
|
||||
clearValue.depth = depth;
|
||||
clearValue.stencil = stencil;
|
||||
|
||||
VkImageSubresourceRange range = {};
|
||||
range.aspectMask = GetImageAspectMask(texture->GetFormat());
|
||||
range.baseMipLevel = 0;
|
||||
range.levelCount = 1;
|
||||
range.baseArrayLayer = 0;
|
||||
range.layerCount = 1;
|
||||
|
||||
vkCmdClearDepthStencilImage(
|
||||
m_commandBuffer,
|
||||
texture->GetImage(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
&clearValue,
|
||||
1,
|
||||
&range);
|
||||
|
||||
TransitionTexture(texture, ResourceStates::DepthWrite);
|
||||
return;
|
||||
}
|
||||
|
||||
EndActiveRenderPass();
|
||||
|
||||
VulkanTexture* texture = depthView->GetTexture();
|
||||
TransitionTexture(texture, ResourceStates::CopyDst);
|
||||
|
||||
VkClearDepthStencilValue clearValue = {};
|
||||
clearValue.depth = depth;
|
||||
clearValue.stencil = stencil;
|
||||
|
||||
VkImageSubresourceRange range = {};
|
||||
range.aspectMask = GetImageAspectMask(texture->GetFormat());
|
||||
range.baseMipLevel = 0;
|
||||
range.levelCount = 1;
|
||||
range.baseArrayLayer = 0;
|
||||
range.layerCount = 1;
|
||||
|
||||
vkCmdClearDepthStencilImage(
|
||||
m_commandBuffer,
|
||||
texture->GetImage(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
&clearValue,
|
||||
1,
|
||||
&range);
|
||||
|
||||
TransitionTexture(texture, ResourceStates::DepthWrite);
|
||||
|
||||
std::vector<VkClearRect> clearRects;
|
||||
clearRects.reserve(rectCount);
|
||||
for (uint32_t i = 0; i < rectCount; ++i) {
|
||||
VkClearRect clearRect = {};
|
||||
if (ClampVulkanClearRect(rects[i], texture->GetWidth(), texture->GetHeight(), clearRect)) {
|
||||
clearRects.push_back(clearRect);
|
||||
}
|
||||
}
|
||||
if (clearRects.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
VkRenderPass renderPass = CreateTransientClearRenderPass(
|
||||
m_device->GetDevice(),
|
||||
false,
|
||||
Format::Unknown,
|
||||
true,
|
||||
texture->GetFormat());
|
||||
if (renderPass == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const VkImageView attachments[] = { depthView->GetImageView() };
|
||||
VkFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebufferInfo.renderPass = renderPass;
|
||||
framebufferInfo.attachmentCount = 1;
|
||||
framebufferInfo.pAttachments = attachments;
|
||||
framebufferInfo.width = texture->GetWidth();
|
||||
framebufferInfo.height = texture->GetHeight();
|
||||
framebufferInfo.layers = 1;
|
||||
|
||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||
if (vkCreateFramebuffer(m_device->GetDevice(), &framebufferInfo, nullptr, &framebuffer) != VK_SUCCESS) {
|
||||
vkDestroyRenderPass(m_device->GetDevice(), renderPass, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
VkRenderPassBeginInfo beginInfo = {};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
beginInfo.renderPass = renderPass;
|
||||
beginInfo.framebuffer = framebuffer;
|
||||
beginInfo.renderArea.offset = { 0, 0 };
|
||||
beginInfo.renderArea.extent = { texture->GetWidth(), texture->GetHeight() };
|
||||
beginInfo.clearValueCount = 0;
|
||||
beginInfo.pClearValues = nullptr;
|
||||
|
||||
vkCmdBeginRenderPass(m_commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
VkClearAttachment attachment = {};
|
||||
attachment.aspectMask = GetImageAspectMask(texture->GetFormat());
|
||||
attachment.clearValue.depthStencil.depth = depth;
|
||||
attachment.clearValue.depthStencil.stencil = stencil;
|
||||
vkCmdClearAttachments(
|
||||
m_commandBuffer,
|
||||
1,
|
||||
&attachment,
|
||||
static_cast<uint32_t>(clearRects.size()),
|
||||
clearRects.data());
|
||||
|
||||
vkCmdEndRenderPass(m_commandBuffer);
|
||||
vkDestroyFramebuffer(m_device->GetDevice(), framebuffer, nullptr);
|
||||
vkDestroyRenderPass(m_device->GetDevice(), renderPass, nullptr);
|
||||
}
|
||||
|
||||
void VulkanCommandList::CopyResource(RHIResourceView* dst, RHIResourceView* src) {
|
||||
|
||||
@@ -343,6 +343,7 @@ bool BuiltinForwardPipeline::ExecuteForwardOpaquePass(const RenderPassContext& p
|
||||
renderArea.x + renderArea.width,
|
||||
renderArea.y + renderArea.height
|
||||
};
|
||||
const RHI::Rect clearRects[] = { scissorRect };
|
||||
commandList->SetViewport(viewport);
|
||||
commandList->SetScissorRect(scissorRect);
|
||||
|
||||
@@ -353,13 +354,13 @@ bool BuiltinForwardPipeline::ExecuteForwardOpaquePass(const RenderPassContext& p
|
||||
if (HasRenderClearFlag(sceneData.cameraData.clearFlags, RenderClearFlags::Color)) {
|
||||
for (RHI::RHIResourceView* renderTarget : renderTargets) {
|
||||
if (renderTarget != nullptr) {
|
||||
commandList->ClearRenderTarget(renderTarget, clearValues);
|
||||
commandList->ClearRenderTarget(renderTarget, clearValues, 1, clearRects);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (surface.GetDepthAttachment() != nullptr &&
|
||||
HasRenderClearFlag(sceneData.cameraData.clearFlags, RenderClearFlags::Depth)) {
|
||||
commandList->ClearDepthStencil(surface.GetDepthAttachment(), 1.0f, 0);
|
||||
commandList->ClearDepthStencil(surface.GetDepthAttachment(), 1.0f, 0, 1, clearRects);
|
||||
}
|
||||
|
||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||
|
||||
@@ -309,6 +309,39 @@ TEST_P(RHITestFixture, CommandList_ClearRenderTarget_WithRealView) {
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST_P(RHITestFixture, CommandList_ClearRenderTarget_WithRect) {
|
||||
TextureDesc texDesc = {};
|
||||
texDesc.width = 256;
|
||||
texDesc.height = 256;
|
||||
texDesc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
texDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||
RHITexture* texture = GetDevice()->CreateTexture(texDesc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
|
||||
ResourceViewDesc viewDesc = {};
|
||||
viewDesc.format = texDesc.format;
|
||||
RHIResourceView* rtv = GetDevice()->CreateRenderTargetView(texture, viewDesc);
|
||||
ASSERT_NE(rtv, nullptr);
|
||||
|
||||
float color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
|
||||
const Rect clearRect = { 64, 64, 192, 192 };
|
||||
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->ClearRenderTarget(rtv, color, 1, &clearRect);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
delete rtv;
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST_P(RHITestFixture, CommandList_ClearDepthStencil_WithRealView) {
|
||||
TextureDesc texDesc = {};
|
||||
texDesc.width = 256;
|
||||
@@ -337,6 +370,36 @@ TEST_P(RHITestFixture, CommandList_ClearDepthStencil_WithRealView) {
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST_P(RHITestFixture, CommandList_ClearDepthStencil_WithRect) {
|
||||
TextureDesc texDesc = {};
|
||||
texDesc.width = 256;
|
||||
texDesc.height = 256;
|
||||
texDesc.format = static_cast<uint32_t>(Format::D24_UNorm_S8_UInt);
|
||||
texDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||
RHITexture* texture = GetDevice()->CreateTexture(texDesc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
|
||||
RHIResourceView* dsv = GetDevice()->CreateDepthStencilView(texture, {});
|
||||
ASSERT_NE(dsv, nullptr);
|
||||
|
||||
const Rect clearRect = { 32, 32, 224, 224 };
|
||||
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->ClearDepthStencil(dsv, 1.0f, 0, 1, &clearRect);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
delete dsv;
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST_P(RHITestFixture, CommandList_TransitionBarrier_WithRealResource) {
|
||||
TextureDesc texDesc = {};
|
||||
texDesc.width = 256;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -294,6 +294,9 @@ void CameraStackSceneTest::BuildScene() {
|
||||
overlayCamera->SetFarClipPlane(10.0f);
|
||||
overlayCamera->SetStackType(CameraStackType::Overlay);
|
||||
overlayCamera->SetCullingMask(1u << kOverlayLayer);
|
||||
overlayCamera->SetClearMode(CameraClearMode::ColorAndDepth);
|
||||
overlayCamera->SetViewportRect(XCEngine::Math::Rect(0.60f, 0.10f, 0.28f, 0.32f));
|
||||
overlayCamera->SetClearColor(XCEngine::Math::Color(0.11f, 0.16f, 0.24f, 1.0f));
|
||||
|
||||
const Vector3 boundsMin = mBackpackMesh->GetBounds().GetMin();
|
||||
const Vector3 boundsMax = mBackpackMesh->GetBounds().GetMax();
|
||||
@@ -334,8 +337,8 @@ void CameraStackSceneTest::BuildScene() {
|
||||
|
||||
GameObject* overlayQuadObject = mScene->CreateGameObject("OverlayQuad");
|
||||
overlayQuadObject->SetLayer(kOverlayLayer);
|
||||
overlayQuadObject->GetTransform()->SetLocalPosition(Vector3(1.0f, 0.58f, 2.0f));
|
||||
overlayQuadObject->GetTransform()->SetLocalScale(Vector3(0.35f, 0.35f, 1.0f));
|
||||
overlayQuadObject->GetTransform()->SetLocalPosition(Vector3(0.0f, 0.0f, 2.0f));
|
||||
overlayQuadObject->GetTransform()->SetLocalScale(Vector3(0.70f, 0.70f, 1.0f));
|
||||
|
||||
auto* overlayMeshFilter = overlayQuadObject->AddComponent<MeshFilterComponent>();
|
||||
auto* overlayMeshRenderer = overlayQuadObject->AddComponent<MeshRendererComponent>();
|
||||
|
||||
Reference in New Issue
Block a user