#include "fixtures/RHITestFixture.h" #include "XCEngine/RHI/RHICommandList.h" #include "XCEngine/RHI/RHITexture.h" #include "XCEngine/RHI/RHIBuffer.h" #include "XCEngine/RHI/RHIShader.h" #include "XCEngine/RHI/RHIPipelineState.h" #include "XCEngine/RHI/RHIRenderPass.h" #include "XCEngine/RHI/RHIFramebuffer.h" #include "XCEngine/RHI/OpenGL/OpenGLDevice.h" #include "XCEngine/RHI/OpenGL/OpenGLResourceView.h" #include #include using namespace XCEngine::RHI; TEST_P(RHITestFixture, CommandList_Reset_Close) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_SetPrimitiveTopology) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_SetViewport) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); Viewport vp = { 0.0f, 0.0f, 800.0f, 600.0f, 0.0f, 1.0f }; cmdList->Reset(); cmdList->SetViewport(vp); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_SetViewports) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); Viewport viewports[2] = { { 0.0f, 0.0f, 400.0f, 300.0f, 0.0f, 1.0f }, { 400.0f, 300.0f, 400.0f, 300.0f, 0.0f, 1.0f } }; cmdList->Reset(); cmdList->SetViewports(2, viewports); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_SetScissorRect) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); Rect rect = { 0, 0, 800, 600 }; cmdList->Reset(); cmdList->SetScissorRect(rect); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_SetScissorRects_Multiple) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); Rect rects[2] = { { 0, 0, 400, 300 }, { 400, 300, 800, 600 } }; cmdList->Reset(); cmdList->SetScissorRects(2, rects); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_Draw) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList); cmdList->Draw(3); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_DrawIndexed) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList); cmdList->DrawIndexed(6); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_SetVertexBuffers_WithRealView) { BufferDesc bufferDesc = {}; bufferDesc.size = 256; bufferDesc.stride = 32; bufferDesc.bufferType = static_cast(BufferType::Vertex); RHIBuffer* buffer = GetDevice()->CreateBuffer(bufferDesc); ASSERT_NE(buffer, nullptr); ResourceViewDesc viewDesc = {}; viewDesc.dimension = ResourceViewDimension::Buffer; viewDesc.structureByteStride = 32; RHIResourceView* vbv = GetDevice()->CreateVertexBufferView(buffer, viewDesc); ASSERT_NE(vbv, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); uint64_t offsets[] = { 0 }; uint32_t strides[] = { 32 }; cmdList->Reset(); cmdList->SetVertexBuffers(0, 1, &vbv, offsets, strides); cmdList->Close(); cmdList->Shutdown(); delete cmdList; vbv->Shutdown(); delete vbv; buffer->Shutdown(); delete buffer; } TEST_P(RHITestFixture, CommandList_SetIndexBuffer_WithRealView) { BufferDesc bufferDesc = {}; bufferDesc.size = 256; bufferDesc.stride = sizeof(uint32_t); bufferDesc.bufferType = static_cast(BufferType::Index); RHIBuffer* buffer = GetDevice()->CreateBuffer(bufferDesc); ASSERT_NE(buffer, nullptr); ResourceViewDesc viewDesc = {}; viewDesc.dimension = ResourceViewDimension::Buffer; viewDesc.format = static_cast(Format::R32_UInt); RHIResourceView* ibv = GetDevice()->CreateIndexBufferView(buffer, viewDesc); ASSERT_NE(ibv, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->SetIndexBuffer(ibv, 0); cmdList->Close(); cmdList->Shutdown(); delete cmdList; ibv->Shutdown(); delete ibv; buffer->Shutdown(); delete buffer; } TEST_P(RHITestFixture, CommandList_SetStencilRef) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->SetStencilRef(0); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_SetBlendFactor) { CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); float blendFactor[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; cmdList->Reset(); cmdList->SetBlendFactor(blendFactor); cmdList->Close(); cmdList->Shutdown(); delete cmdList; } TEST_P(RHITestFixture, CommandList_ClearRenderTarget_WithRealView) { TextureDesc texDesc = {}; texDesc.width = 256; texDesc.height = 256; texDesc.format = static_cast(Format::R8G8B8A8_UNorm); texDesc.textureType = static_cast(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] = { 1.0f, 0.0f, 0.0f, 1.0f }; CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->ClearRenderTarget(rtv, color); cmdList->Close(); cmdList->Shutdown(); delete cmdList; delete rtv; texture->Shutdown(); delete texture; } TEST_P(RHITestFixture, CommandList_ClearDepthStencil_WithRealView) { TextureDesc texDesc = {}; texDesc.width = 256; texDesc.height = 256; texDesc.format = static_cast(Format::D24_UNorm_S8_UInt); texDesc.textureType = static_cast(TextureType::Texture2D); RHITexture* texture = GetDevice()->CreateTexture(texDesc); ASSERT_NE(texture, nullptr); RHIResourceView* dsv = GetDevice()->CreateDepthStencilView(texture, {}); ASSERT_NE(dsv, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->ClearDepthStencil(dsv, 1.0f, 0); cmdList->Close(); cmdList->Shutdown(); delete cmdList; delete dsv; texture->Shutdown(); delete texture; } TEST_P(RHITestFixture, CommandList_TransitionBarrier_WithRealResource) { TextureDesc texDesc = {}; texDesc.width = 256; texDesc.height = 256; texDesc.format = static_cast(Format::R8G8B8A8_UNorm); texDesc.textureType = static_cast(TextureType::Texture2D); RHITexture* texture = GetDevice()->CreateTexture(texDesc); ASSERT_NE(texture, nullptr); RHIResourceView* srv = GetDevice()->CreateShaderResourceView(texture, {}); ASSERT_NE(srv, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->TransitionBarrier(srv, ResourceStates::Common, ResourceStates::PixelShaderResource); cmdList->Close(); cmdList->Shutdown(); delete cmdList; delete srv; texture->Shutdown(); delete texture; } TEST_P(RHITestFixture, CommandList_SetRenderTargets_WithRealViews) { TextureDesc texDesc = {}; texDesc.width = 256; texDesc.height = 256; texDesc.format = static_cast(Format::R8G8B8A8_UNorm); texDesc.textureType = static_cast(TextureType::Texture2D); RHITexture* texture = GetDevice()->CreateTexture(texDesc); ASSERT_NE(texture, nullptr); RHIResourceView* rtv = GetDevice()->CreateRenderTargetView(texture, {}); ASSERT_NE(rtv, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->SetRenderTargets(1, &rtv, nullptr); cmdList->Close(); cmdList->Shutdown(); delete cmdList; delete rtv; texture->Shutdown(); delete texture; } TEST_P(RHITestFixture, CommandList_SetRenderTargets_BindsColorAndDepthAttachmentsOnOpenGL) { if (GetBackendType() != RHIType::OpenGL) { GTEST_SKIP() << "OpenGL-specific framebuffer attachment verification"; } TextureDesc colorDesc = {}; colorDesc.width = 128; colorDesc.height = 128; colorDesc.format = static_cast(Format::R8G8B8A8_UNorm); colorDesc.textureType = static_cast(TextureType::Texture2D); TextureDesc depthDesc = {}; depthDesc.width = 128; depthDesc.height = 128; depthDesc.format = static_cast(Format::D24_UNorm_S8_UInt); depthDesc.textureType = static_cast(TextureType::Texture2D); RHITexture* colorTexture = GetDevice()->CreateTexture(colorDesc); RHITexture* depthTexture = GetDevice()->CreateTexture(depthDesc); ASSERT_NE(colorTexture, nullptr); ASSERT_NE(depthTexture, nullptr); ResourceViewDesc colorViewDesc = {}; colorViewDesc.format = colorDesc.format; RHIResourceView* rtv = GetDevice()->CreateRenderTargetView(colorTexture, colorViewDesc); ResourceViewDesc depthViewDesc = {}; depthViewDesc.format = depthDesc.format; RHIResourceView* dsv = GetDevice()->CreateDepthStencilView(depthTexture, depthViewDesc); ASSERT_NE(rtv, nullptr); ASSERT_NE(dsv, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->SetRenderTargets(1, &rtv, dsv); GLint framebuffer = 0; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &framebuffer); EXPECT_NE(framebuffer, 0); EXPECT_EQ(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE); GLint colorAttachment = 0; glGetFramebufferAttachmentParameteriv( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &colorAttachment); EXPECT_EQ(static_cast(colorAttachment), static_cast(rtv)->GetTexture()); GLint depthAttachment = 0; glGetFramebufferAttachmentParameteriv( GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthAttachment); EXPECT_EQ(static_cast(depthAttachment), static_cast(dsv)->GetTexture()); cmdList->Close(); cmdList->Shutdown(); delete cmdList; delete dsv; delete rtv; depthTexture->Shutdown(); delete depthTexture; colorTexture->Shutdown(); delete colorTexture; } TEST_P(RHITestFixture, CommandList_SetRenderTargets_BindsMultipleColorAttachmentsOnOpenGL) { if (GetBackendType() != RHIType::OpenGL) { GTEST_SKIP() << "OpenGL-specific multiple render target verification"; } TextureDesc texDesc = {}; texDesc.width = 128; texDesc.height = 128; texDesc.format = static_cast(Format::R8G8B8A8_UNorm); texDesc.textureType = static_cast(TextureType::Texture2D); RHITexture* texture0 = GetDevice()->CreateTexture(texDesc); RHITexture* texture1 = GetDevice()->CreateTexture(texDesc); ASSERT_NE(texture0, nullptr); ASSERT_NE(texture1, nullptr); ResourceViewDesc viewDesc = {}; viewDesc.format = texDesc.format; RHIResourceView* rtv0 = GetDevice()->CreateRenderTargetView(texture0, viewDesc); RHIResourceView* rtv1 = GetDevice()->CreateRenderTargetView(texture1, viewDesc); ASSERT_NE(rtv0, nullptr); ASSERT_NE(rtv1, nullptr); RHIResourceView* rtvs[] = { rtv0, rtv1 }; CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->SetRenderTargets(2, rtvs, nullptr); GLint framebuffer = 0; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &framebuffer); EXPECT_NE(framebuffer, 0); EXPECT_EQ(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE); GLint colorAttachment0 = 0; glGetFramebufferAttachmentParameteriv( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &colorAttachment0); EXPECT_EQ(static_cast(colorAttachment0), static_cast(rtv0)->GetTexture()); GLint colorAttachment1 = 0; glGetFramebufferAttachmentParameteriv( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &colorAttachment1); EXPECT_EQ(static_cast(colorAttachment1), static_cast(rtv1)->GetTexture()); cmdList->Close(); cmdList->Shutdown(); delete cmdList; delete rtv1; delete rtv0; texture1->Shutdown(); delete texture1; texture0->Shutdown(); delete texture0; } TEST_P(RHITestFixture, CommandList_CopyResource_WithRealResources) { TextureDesc texDesc = {}; texDesc.width = 256; texDesc.height = 256; texDesc.format = static_cast(Format::R8G8B8A8_UNorm); texDesc.textureType = static_cast(TextureType::Texture2D); RHITexture* srcTexture = GetDevice()->CreateTexture(texDesc); ASSERT_NE(srcTexture, nullptr); RHITexture* dstTexture = GetDevice()->CreateTexture(texDesc); ASSERT_NE(dstTexture, nullptr); RHIResourceView* srcView = GetDevice()->CreateShaderResourceView(srcTexture, {}); RHIResourceView* dstView = GetDevice()->CreateShaderResourceView(dstTexture, {}); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->CopyResource(dstView, srcView); cmdList->Close(); cmdList->Shutdown(); delete cmdList; delete srcView; delete dstView; srcTexture->Shutdown(); delete srcTexture; dstTexture->Shutdown(); delete dstTexture; } TEST_P(RHITestFixture, CommandList_CopyResource_UsesActualTextureDimensionsOnOpenGL) { if (GetBackendType() != RHIType::OpenGL) { GTEST_SKIP() << "OpenGL-specific copy verification"; } constexpr uint32_t kWidth = 64; constexpr uint32_t kHeight = 32; std::vector srcPixels(kWidth * kHeight * 4); for (uint32_t y = 0; y < kHeight; ++y) { for (uint32_t x = 0; x < kWidth; ++x) { const size_t index = static_cast((y * kWidth + x) * 4); srcPixels[index + 0] = static_cast(x * 3); srcPixels[index + 1] = static_cast(y * 5); srcPixels[index + 2] = static_cast((x + y) * 7); srcPixels[index + 3] = 255; } } TextureDesc texDesc = {}; texDesc.width = kWidth; texDesc.height = kHeight; texDesc.depth = 1; texDesc.mipLevels = 1; texDesc.arraySize = 1; texDesc.format = static_cast(Format::R8G8B8A8_UNorm); texDesc.textureType = static_cast(TextureType::Texture2D); texDesc.sampleCount = 1; texDesc.sampleQuality = 0; RHITexture* srcTexture = GetDevice()->CreateTexture(texDesc, srcPixels.data(), srcPixels.size(), kWidth * 4); ASSERT_NE(srcTexture, nullptr); RHITexture* dstTexture = GetDevice()->CreateTexture(texDesc); ASSERT_NE(dstTexture, nullptr); RHIResourceView* srcView = GetDevice()->CreateShaderResourceView(srcTexture, {}); RHIResourceView* dstView = GetDevice()->CreateShaderResourceView(dstTexture, {}); ASSERT_NE(srcView, nullptr); ASSERT_NE(dstView, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->CopyResource(dstView, srcView); glFinish(); cmdList->Close(); std::vector dstPixels(kWidth * kHeight * 4, 0); const GLuint dstTextureId = static_cast(dstView)->GetTexture(); glBindTexture(GL_TEXTURE_2D, dstTextureId); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, dstPixels.data()); glBindTexture(GL_TEXTURE_2D, 0); EXPECT_EQ(dstPixels, srcPixels); cmdList->Shutdown(); delete cmdList; delete srcView; delete dstView; srcTexture->Shutdown(); delete srcTexture; dstTexture->Shutdown(); delete dstTexture; } TEST_P(RHITestFixture, CommandList_BeginEndRenderPass_Basic) { AttachmentDesc colorDesc = {}; colorDesc.format = Format::R8G8B8A8_UNorm; colorDesc.loadOp = LoadAction::Clear; colorDesc.storeOp = StoreAction::Store; RHIRenderPass* renderPass = GetDevice()->CreateRenderPass(1, &colorDesc, nullptr); ASSERT_NE(renderPass, nullptr); TextureDesc texDesc = {}; texDesc.width = 256; texDesc.height = 256; texDesc.format = static_cast(Format::R8G8B8A8_UNorm); texDesc.textureType = static_cast(TextureType::Texture2D); RHITexture* texture = GetDevice()->CreateTexture(texDesc); ASSERT_NE(texture, nullptr); RHIResourceView* rtv = GetDevice()->CreateRenderTargetView(texture, {}); ASSERT_NE(rtv, nullptr); RHIFramebuffer* fb = GetDevice()->CreateFramebuffer(renderPass, 256, 256, 1, &rtv, nullptr); ASSERT_NE(fb, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); Rect renderArea = { 0, 0, 256, 256 }; ClearValue clearValue = { { 0.0f, 0.0f, 0.0f, 1.0f }, 1.0f, 0 }; cmdList->Reset(); cmdList->BeginRenderPass(renderPass, fb, renderArea, 1, &clearValue); cmdList->EndRenderPass(); cmdList->Close(); cmdList->Shutdown(); delete cmdList; fb->Shutdown(); delete fb; delete rtv; texture->Shutdown(); delete texture; renderPass->Shutdown(); delete renderPass; } TEST_P(RHITestFixture, CommandList_BeginEndRenderPass_WithClear) { AttachmentDesc colorDesc = {}; colorDesc.format = Format::R8G8B8A8_UNorm; colorDesc.loadOp = LoadAction::Clear; colorDesc.storeOp = StoreAction::Store; RHIRenderPass* renderPass = GetDevice()->CreateRenderPass(1, &colorDesc, nullptr); ASSERT_NE(renderPass, nullptr); TextureDesc texDesc = {}; texDesc.width = 256; texDesc.height = 256; texDesc.format = static_cast(Format::R8G8B8A8_UNorm); texDesc.textureType = static_cast(TextureType::Texture2D); RHITexture* texture = GetDevice()->CreateTexture(texDesc); ASSERT_NE(texture, nullptr); RHIResourceView* rtv = GetDevice()->CreateRenderTargetView(texture, {}); ASSERT_NE(rtv, nullptr); RHIFramebuffer* fb = GetDevice()->CreateFramebuffer(renderPass, 256, 256, 1, &rtv, nullptr); ASSERT_NE(fb, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); Rect renderArea = { 0, 0, 256, 256 }; ClearValue clearValue = { { 1.0f, 0.0f, 0.0f, 1.0f }, 1.0f, 0 }; cmdList->Reset(); cmdList->BeginRenderPass(renderPass, fb, renderArea, 1, &clearValue); cmdList->EndRenderPass(); cmdList->Close(); cmdList->Shutdown(); delete cmdList; fb->Shutdown(); delete fb; delete rtv; texture->Shutdown(); delete texture; renderPass->Shutdown(); delete renderPass; } TEST_P(RHITestFixture, CommandList_SetShader) { ShaderCompileDesc shaderDesc = {}; if (GetBackendType() == RHIType::D3D12) { shaderDesc.fileName = L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl"; shaderDesc.entryPoint = L"MainVS"; shaderDesc.profile = L"vs_5_0"; } else { shaderDesc.sourceLanguage = ShaderLanguage::GLSL; static const char* vs = "#version 430\nin vec4 aPosition;\nvoid main() { gl_Position = aPosition; }"; shaderDesc.source.assign(vs, vs + strlen(vs)); } RHIShader* shader = GetDevice()->CreateShader(shaderDesc); if (shader == nullptr) { return; } CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); cmdList->Reset(); cmdList->SetShader(shader); cmdList->Close(); cmdList->Shutdown(); delete cmdList; shader->Shutdown(); delete shader; } TEST_P(RHITestFixture, CommandList_SetVertexBuffers_InterleavedInputLayoutUsesPipelineLayout) { if (GetBackendType() != RHIType::OpenGL) { GTEST_SKIP() << "OpenGL-specific vertex layout binding"; } auto* openGLDevice = static_cast(GetDevice()); ASSERT_NE(openGLDevice, nullptr); ASSERT_TRUE(openGLDevice->MakeContextCurrent()); GraphicsPipelineDesc pipelineDesc = {}; pipelineDesc.renderTargetFormats[0] = static_cast(Format::R8G8B8A8_UNorm); InputElementDesc position = {}; position.semanticName = "POSITION"; position.semanticIndex = 0; position.format = static_cast(Format::R32G32B32A32_Float); position.inputSlot = 0; position.alignedByteOffset = 0; pipelineDesc.inputLayout.elements.push_back(position); InputElementDesc color = {}; color.semanticName = "COLOR"; color.semanticIndex = 0; color.format = static_cast(Format::R32G32B32A32_Float); color.inputSlot = 0; color.alignedByteOffset = sizeof(float) * 4; pipelineDesc.inputLayout.elements.push_back(color); static const char* vertexSource = R"(#version 430 layout(location = 0) in vec4 aPosition; layout(location = 1) in vec4 aColor; out vec4 vColor; void main() { gl_Position = aPosition; vColor = aColor; } )"; static const char* fragmentSource = R"(#version 430 in vec4 vColor; layout(location = 0) out vec4 fragColor; void main() { fragColor = vColor; } )"; pipelineDesc.vertexShader.source.assign(vertexSource, vertexSource + strlen(vertexSource)); pipelineDesc.vertexShader.sourceLanguage = ShaderLanguage::GLSL; pipelineDesc.vertexShader.profile = L"vs_4_30"; pipelineDesc.fragmentShader.source.assign(fragmentSource, fragmentSource + strlen(fragmentSource)); pipelineDesc.fragmentShader.sourceLanguage = ShaderLanguage::GLSL; pipelineDesc.fragmentShader.profile = L"fs_4_30"; RHIPipelineState* pipelineState = GetDevice()->CreatePipelineState(pipelineDesc); ASSERT_NE(pipelineState, nullptr); BufferDesc bufferDesc = {}; bufferDesc.size = sizeof(float) * 8 * 3; bufferDesc.stride = sizeof(float) * 8; bufferDesc.bufferType = static_cast(BufferType::Vertex); RHIBuffer* buffer = GetDevice()->CreateBuffer(bufferDesc); ASSERT_NE(buffer, nullptr); ResourceViewDesc viewDesc = {}; viewDesc.dimension = ResourceViewDimension::Buffer; viewDesc.structureByteStride = bufferDesc.stride; RHIResourceView* vbv = GetDevice()->CreateVertexBufferView(buffer, viewDesc); ASSERT_NE(vbv, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc); ASSERT_NE(cmdList, nullptr); RHIResourceView* views[] = { vbv }; uint64_t offsets[] = { 0 }; uint32_t strides[] = { bufferDesc.stride }; cmdList->Reset(); cmdList->SetPipelineState(pipelineState); cmdList->SetVertexBuffers(0, 1, views, offsets, strides); GLint enabled0 = 0; GLint enabled1 = 0; GLint size0 = 0; GLint size1 = 0; GLint stride0 = 0; GLint stride1 = 0; void* pointer0 = nullptr; void* pointer1 = nullptr; glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled0); glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled1); glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size0); glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size1); glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride0); glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride1); glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &pointer0); glGetVertexAttribPointerv(1, GL_VERTEX_ATTRIB_ARRAY_POINTER, &pointer1); EXPECT_EQ(enabled0, GL_TRUE); EXPECT_EQ(enabled1, GL_TRUE); EXPECT_EQ(size0, 4); EXPECT_EQ(size1, 4); EXPECT_EQ(stride0, static_cast(bufferDesc.stride)); EXPECT_EQ(stride1, static_cast(bufferDesc.stride)); EXPECT_EQ(reinterpret_cast(pointer0), 0u); EXPECT_EQ(reinterpret_cast(pointer1), sizeof(float) * 4u); cmdList->Close(); cmdList->Shutdown(); delete cmdList; vbv->Shutdown(); delete vbv; buffer->Shutdown(); delete buffer; pipelineState->Shutdown(); delete pipelineState; }