renderer_test.cxx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. //
  2. // direct_renderer_test.cxx
  3. // graphics-test
  4. //
  5. // Created by Sam Jaffe on 6/1/19.
  6. // Copyright © 2019 Sam Jaffe. All rights reserved.
  7. //
  8. #include <gmock/gmock.h>
  9. #include "../src/renderer_impl.hpp"
  10. #include "game/graphics/object.hpp"
  11. #include "game/graphics/renderer.hpp"
  12. #include "game/graphics/vertex.h"
  13. #include "game/math/shape.hpp"
  14. #include "matrix/matrix.hpp"
  15. #include "matrix/matrix_helpers.hpp"
  16. using testing::_;
  17. using testing::AnyNumber;
  18. using testing::IsEmpty;
  19. using testing::SizeIs;
  20. struct mock_renderer_impl : graphics::renderer_impl {
  21. MOCK_CONST_METHOD0(manager, std::shared_ptr<graphics::manager const>());
  22. MOCK_METHOD3(draw, void(identity<graphics::material>, math::matr4 const &,
  23. std::vector<graphics::vertex> const &));
  24. MOCK_METHOD0(clear, void());
  25. MOCK_METHOD0(flush, void());
  26. };
  27. identity<graphics::material> cast(unsigned int id) {
  28. return *reinterpret_cast<identity<graphics::material> *>(&id);
  29. }
  30. struct DirectRendererTest : testing::Test {
  31. void SetUp() override;
  32. void TearDown() override;
  33. std::unique_ptr<graphics::direct_renderer> renderer;
  34. mock_renderer_impl * mock;
  35. };
  36. void DirectRendererTest::SetUp() {
  37. mock = new mock_renderer_impl;
  38. renderer.reset(new graphics::direct_renderer(mock));
  39. }
  40. void DirectRendererTest::TearDown() {
  41. renderer.reset();
  42. delete mock;
  43. }
  44. graphics::object DemoObject(unsigned int id = 1) {
  45. math::dim2::rectangle const size{{{-1.f, -1.f}}, {{2.f, 2.f}}};
  46. math::dim2::rectangle const tex{{{0.f, 0.f}}, {{1.f, 1.f}}};
  47. return {size, size, cast(id), tex};
  48. }
  49. TEST_F(DirectRendererTest, DrawPassesToDraw) {
  50. EXPECT_CALL(*mock, draw(cast(1), math::matr4(), IsEmpty())).Times(1);
  51. renderer->draw(cast(1), math::matr4(), {});
  52. }
  53. TEST_F(DirectRendererTest, DrawObjectHasIdenTranslation) {
  54. auto identity = math::matrix::identity<float, 4>();
  55. EXPECT_CALL(*mock, draw(cast(1), identity, _)).Times(1);
  56. renderer->draw(DemoObject());
  57. }
  58. TEST_F(DirectRendererTest, DrawObjectHasSixVertices) {
  59. EXPECT_CALL(*mock, draw(_, _, SizeIs(6))).Times(1);
  60. renderer->draw(DemoObject());
  61. }
  62. TEST_F(DirectRendererTest, MultipleDrawCallsDispatchMultipleDraws) {
  63. EXPECT_CALL(*mock, draw(_, _, SizeIs(6))).Times(2);
  64. renderer->draw(DemoObject());
  65. renderer->draw(DemoObject());
  66. }
  67. TEST_F(DirectRendererTest, ClearPassesToClear) {
  68. EXPECT_CALL(*mock, clear()).Times(1);
  69. renderer->clear();
  70. }
  71. TEST_F(DirectRendererTest, FlushPassesToFlush) {
  72. EXPECT_CALL(*mock, flush()).Times(1);
  73. renderer->flush();
  74. }
  75. struct BatchRendererTest : testing::Test {
  76. void SetUp() override;
  77. void TearDown() override;
  78. std::unique_ptr<graphics::batch_renderer> renderer;
  79. std::unique_ptr<graphics::direct_renderer> drenderer;
  80. mock_renderer_impl * mock;
  81. };
  82. void BatchRendererTest::SetUp() {
  83. mock = new mock_renderer_impl;
  84. drenderer.reset(new graphics::direct_renderer(mock));
  85. renderer.reset(new graphics::batch_renderer(drenderer.get()));
  86. }
  87. void BatchRendererTest::TearDown() {
  88. renderer.reset();
  89. drenderer.reset();
  90. delete mock;
  91. }
  92. TEST_F(BatchRendererTest, DoesNotCallFlushOnDestructor) {
  93. EXPECT_CALL(*mock, flush()).Times(0);
  94. renderer.reset();
  95. testing::Mock::VerifyAndClearExpectations(mock);
  96. }
  97. TEST_F(BatchRendererTest, ClearPassesToClear) {
  98. EXPECT_CALL(*mock, flush()).Times(AnyNumber());
  99. EXPECT_CALL(*mock, clear()).Times(1);
  100. renderer->clear();
  101. }
  102. TEST_F(BatchRendererTest, FlushDoesNotPassToFlush) {
  103. EXPECT_CALL(*mock, flush()).Times(0);
  104. renderer->flush();
  105. }
  106. TEST_F(BatchRendererTest, DoesNotWriteImmediately) {
  107. EXPECT_CALL(*mock, draw(_, _, _)).Times(0);
  108. renderer->draw(cast(1), math::matr4(), {});
  109. testing::Mock::VerifyAndClearExpectations(mock);
  110. // We need to re-enact this expectation
  111. EXPECT_CALL(*mock, flush()).Times(AnyNumber());
  112. EXPECT_CALL(*mock, draw(_, _, _)).Times(1);
  113. }
  114. TEST_F(BatchRendererTest, GroupsDataTogetherByMaterial) {
  115. EXPECT_CALL(*mock, flush()).Times(AnyNumber());
  116. EXPECT_CALL(*mock, draw(cast(1), _, SizeIs(12))).Times(1);
  117. EXPECT_CALL(*mock, draw(cast(2), _, SizeIs(6))).Times(1);
  118. renderer->draw(DemoObject());
  119. renderer->draw(DemoObject());
  120. renderer->draw(DemoObject(2));
  121. }
  122. TEST_F(BatchRendererTest, BatchLimitingCanSplitTheWrites) {
  123. EXPECT_CALL(*mock, flush()).Times(AnyNumber());
  124. renderer.reset(new graphics::batch_renderer(drenderer.get(), 15));
  125. // This sometimes occurs...
  126. EXPECT_CALL(*mock, draw(_, _, SizeIs(0))).Times(AnyNumber());
  127. EXPECT_CALL(*mock, draw(cast(1), _, SizeIs(12))).Times(1);
  128. EXPECT_CALL(*mock, draw(cast(2), _, SizeIs(6))).Times(2);
  129. renderer->draw(DemoObject());
  130. renderer->draw(DemoObject());
  131. renderer->draw(DemoObject(2));
  132. renderer->draw(DemoObject(2));
  133. }