1/*
2 * Copyright (c) 2015-2016 The Khronos Group Inc.
3 * Copyright (c) 2015-2016 Valve Corporation
4 * Copyright (c) 2015-2016 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials are
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included in
14 * all copies or substantial portions of the Materials.
15 *
16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 *
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23 * USE OR OTHER DEALINGS IN THE MATERIALS.
24 *
25 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
26 */
27
28#ifndef VKRENDERFRAMEWORK_H
29#define VKRENDERFRAMEWORK_H
30
31#ifdef ANDROID
32#include "vktestframeworkandroid.h"
33class VkImageObj;
34#else
35#include "vktestframework.h"
36#endif
37
38#include <vector>
39
40using namespace std;
41
42class VkDeviceObj : public vk_testing::Device {
43  public:
44    VkDeviceObj(uint32_t id, VkPhysicalDevice obj);
45    VkDeviceObj(uint32_t id, VkPhysicalDevice obj,
46                std::vector<const char *> &layers,
47                std::vector<const char *> &extension_names);
48
49    VkDevice device() { return handle(); }
50    void get_device_queue();
51
52    uint32_t id;
53    VkPhysicalDeviceProperties props;
54    const VkQueueFamilyProperties *queue_props;
55
56    VkQueue m_queue;
57};
58
59class VkDepthStencilObj : public vk_testing::Image {
60  public:
61    VkDepthStencilObj();
62    void Init(VkDeviceObj *device, int32_t width, int32_t height,
63              VkFormat format);
64    bool Initialized();
65    VkImageView *BindInfo();
66
67  protected:
68    VkDeviceObj *m_device;
69    bool m_initialized;
70    vk_testing::ImageView m_imageView;
71    VkFormat m_depth_stencil_fmt;
72    VkImageView m_attachmentBindInfo;
73};
74
75class VkCommandBufferObj;
76
77class VkRenderFramework : public VkTestFramework {
78  public:
79    VkRenderFramework();
80    ~VkRenderFramework();
81
82    VkDevice device() { return m_device->device(); }
83    VkPhysicalDevice gpu() { return objs[0]; }
84    VkRenderPass renderPass() { return m_renderPass; }
85    VkFramebuffer framebuffer() { return m_framebuffer; }
86    void InitViewport(float width, float height);
87    void InitViewport();
88    void InitRenderTarget();
89    void InitRenderTarget(uint32_t targets);
90    void InitRenderTarget(VkImageView *dsBinding);
91    void InitRenderTarget(uint32_t targets, VkImageView *dsBinding);
92    void InitFramework();
93    void InitFramework(std::vector<const char *> instance_layer_names,
94                       std::vector<const char *> device_layer_names,
95                       std::vector<const char *> instance_extension_names,
96                       std::vector<const char *> device_extension_names,
97                       PFN_vkDebugReportCallbackEXT = NULL,
98                       void *userData = NULL);
99
100    void ShutdownFramework();
101    void InitState();
102
103    const VkRenderPassBeginInfo &renderPassBeginInfo() const {
104        return m_renderPassBeginInfo;
105    }
106
107  protected:
108    VkApplicationInfo app_info;
109    VkInstance inst;
110    VkPhysicalDevice objs[16];
111    uint32_t gpu_count;
112    VkDeviceObj *m_device;
113    VkCommandPool m_commandPool;
114    VkCommandBufferObj *m_commandBuffer;
115    VkRenderPass m_renderPass;
116    VkFramebuffer m_framebuffer;
117    std::vector<VkViewport> m_viewports;
118    std::vector<VkRect2D> m_scissors;
119    float m_lineWidth;
120    float m_depthBiasConstantFactor;
121    float m_depthBiasClamp;
122    float m_depthBiasSlopeFactor;
123    float m_blendConstants[4];
124    float m_minDepthBounds;
125    float m_maxDepthBounds;
126    uint32_t m_compareMask;
127    uint32_t m_writeMask;
128    uint32_t m_reference;
129    std::vector<VkClearValue> m_renderPassClearValues;
130    VkRenderPassBeginInfo m_renderPassBeginInfo;
131    vector<VkImageObj *> m_renderTargets;
132    float m_width, m_height;
133    VkFormat m_render_target_fmt;
134    VkFormat m_depth_stencil_fmt;
135    VkClearColorValue m_clear_color;
136    bool m_clear_via_load_op;
137    float m_depth_clear_color;
138    uint32_t m_stencil_clear_color;
139    VkDepthStencilObj *m_depthStencil;
140    PFN_vkCreateDebugReportCallbackEXT m_CreateDebugReportCallback;
141    PFN_vkDestroyDebugReportCallbackEXT m_DestroyDebugReportCallback;
142    PFN_vkDebugReportMessageEXT m_DebugReportMessage;
143    VkDebugReportCallbackEXT m_globalMsgCallback;
144    VkDebugReportCallbackEXT m_devMsgCallback;
145
146    /*
147     * SetUp and TearDown are called by the Google Test framework
148     * to initialize a test framework based on this class.
149     */
150    virtual void SetUp() {
151        this->app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
152        this->app_info.pNext = NULL;
153        this->app_info.pApplicationName = "base";
154        this->app_info.applicationVersion = 1;
155        this->app_info.pEngineName = "unittest";
156        this->app_info.engineVersion = 1;
157        this->app_info.apiVersion = VK_API_VERSION_1_0;
158
159        InitFramework();
160    }
161
162    virtual void TearDown() { ShutdownFramework(); }
163};
164
165class VkDescriptorSetObj;
166class VkIndexBufferObj;
167class VkConstantBufferObj;
168class VkPipelineObj;
169class VkDescriptorSetObj;
170
171class VkCommandBufferObj : public vk_testing::CommandBuffer {
172  public:
173    VkCommandBufferObj(VkDeviceObj *device, VkCommandPool pool);
174    VkCommandBuffer GetBufferHandle();
175    VkResult BeginCommandBuffer();
176    VkResult BeginCommandBuffer(VkCommandBufferBeginInfo *pInfo);
177    VkResult EndCommandBuffer();
178    void PipelineBarrier(VkPipelineStageFlags src_stages,
179                         VkPipelineStageFlags dest_stages,
180                         VkDependencyFlags dependencyFlags,
181                         uint32_t memoryBarrierCount,
182                         const VkMemoryBarrier *pMemoryBarriers,
183                         uint32_t bufferMemoryBarrierCount,
184                         const VkBufferMemoryBarrier *pBufferMemoryBarriers,
185                         uint32_t imageMemoryBarrierCount,
186                         const VkImageMemoryBarrier *pImageMemoryBarriers);
187    void AddRenderTarget(VkImageObj *renderTarget);
188    void AddDepthStencil();
189    void ClearAllBuffers(VkClearColorValue clear_color, float depth_clear_color,
190                         uint32_t stencil_clear_color,
191                         VkDepthStencilObj *depthStencilObj);
192    void PrepareAttachments();
193    void BindPipeline(VkPipelineObj &pipeline);
194    void BindDescriptorSet(VkDescriptorSetObj &descriptorSet);
195    void BindVertexBuffer(VkConstantBufferObj *vertexBuffer,
196                          VkDeviceSize offset, uint32_t binding);
197    void BindIndexBuffer(VkIndexBufferObj *indexBuffer, VkDeviceSize offset);
198    void BeginRenderPass(const VkRenderPassBeginInfo &info);
199    void EndRenderPass();
200    void FillBuffer(VkBuffer buffer, VkDeviceSize offset,
201                    VkDeviceSize fill_size, uint32_t data);
202    void Draw(uint32_t vertexCount, uint32_t instanceCount,
203              uint32_t firstVertex, uint32_t firstInstance);
204    void DrawIndexed(uint32_t indexCount, uint32_t instanceCount,
205                     uint32_t firstIndex, int32_t vertexOffset,
206                     uint32_t firstInstance);
207    void QueueCommandBuffer();
208    void QueueCommandBuffer(VkFence fence);
209    void SetViewport(uint32_t firstViewport, uint32_t viewportCount,
210                     const VkViewport *pViewports);
211    void SetScissor(uint32_t firstScissor, uint32_t scissorCount,
212                    const VkRect2D *pScissors);
213    void SetLineWidth(float lineWidth);
214    void SetDepthBias(float depthBiasConstantFactor, float depthBiasClamp,
215                      float depthBiasSlopeFactor);
216    void SetBlendConstants(const float blendConstants[4]);
217    void SetDepthBounds(float minDepthBounds, float maxDepthBounds);
218    void SetStencilReadMask(VkStencilFaceFlags faceMask, uint32_t compareMask);
219    void SetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask);
220    void SetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference);
221    void UpdateBuffer(VkBuffer buffer, VkDeviceSize dstOffset,
222                      VkDeviceSize dataSize, const uint32_t *pData);
223    void CopyImage(VkImage srcImage, VkImageLayout srcImageLayout,
224                   VkImage dstImage, VkImageLayout dstImageLayout,
225                   uint32_t regionCount, const VkImageCopy *pRegions);
226    void ResolveImage(VkImage srcImage, VkImageLayout srcImageLayout,
227                      VkImage dstImage, VkImageLayout dstImageLayout,
228                      uint32_t regionCount, const VkImageResolve *pRegions);
229
230  protected:
231    VkDeviceObj *m_device;
232    vector<VkImageObj *> m_renderTargets;
233};
234
235class VkConstantBufferObj : public vk_testing::Buffer {
236  public:
237    VkConstantBufferObj(VkDeviceObj *device);
238    VkConstantBufferObj(VkDeviceObj *device, int constantCount,
239                        int constantSize, const void *data);
240    ~VkConstantBufferObj();
241    void BufferMemoryBarrier(
242        VkFlags srcAccessMask = VK_ACCESS_HOST_WRITE_BIT |
243                                VK_ACCESS_SHADER_WRITE_BIT |
244                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
245                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
246                                VK_ACCESS_TRANSFER_WRITE_BIT,
247        VkFlags dstAccessMask = VK_ACCESS_HOST_READ_BIT |
248                                VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
249                                VK_ACCESS_INDEX_READ_BIT |
250                                VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
251                                VK_ACCESS_UNIFORM_READ_BIT |
252                                VK_ACCESS_SHADER_READ_BIT |
253                                VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
254                                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
255                                VK_ACCESS_MEMORY_READ_BIT);
256
257    void Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset,
258              uint32_t binding);
259
260    VkDescriptorBufferInfo m_descriptorBufferInfo;
261
262  protected:
263    VkDeviceObj *m_device;
264    vk_testing::BufferView m_bufferView;
265    int m_numVertices;
266    int m_stride;
267    vk_testing::CommandPool *m_commandPool;
268    VkCommandBufferObj *m_commandBuffer;
269    vk_testing::Fence m_fence;
270};
271
272class VkIndexBufferObj : public VkConstantBufferObj {
273  public:
274    VkIndexBufferObj(VkDeviceObj *device);
275    void CreateAndInitBuffer(int numIndexes, VkIndexType dataFormat,
276                             const void *data);
277    void Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset);
278    VkIndexType GetIndexType();
279
280  protected:
281    VkIndexType m_indexType;
282};
283
284class VkImageObj : public vk_testing::Image {
285  public:
286    VkImageObj(VkDeviceObj *dev);
287    bool IsCompatible(VkFlags usage, VkFlags features);
288
289  public:
290    void init(uint32_t w, uint32_t h, VkFormat fmt, VkFlags usage,
291              VkImageTiling tiling = VK_IMAGE_TILING_LINEAR,
292              VkMemoryPropertyFlags reqs = 0);
293
294    //    void clear( CommandBuffer*, uint32_t[4] );
295
296    void layout(VkImageLayout layout) {
297        m_descriptorImageInfo.imageLayout = layout;
298    }
299
300    VkDeviceMemory memory() const { return Image::memory().handle(); }
301
302    void *MapMemory() { return Image::memory().map(); }
303
304    void UnmapMemory() { Image::memory().unmap(); }
305
306    void ImageMemoryBarrier(VkCommandBufferObj *cmd, VkImageAspectFlags aspect,
307                            VkFlags output_mask, VkFlags input_mask,
308                            VkImageLayout image_layout);
309
310    VkResult CopyImage(VkImageObj &src_image);
311
312    VkImage image() const { return handle(); }
313
314    VkImageView targetView(VkFormat format) {
315        if (!m_targetView.initialized()) {
316            VkImageViewCreateInfo createView = {};
317            createView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
318            createView.image = handle();
319            createView.viewType = VK_IMAGE_VIEW_TYPE_2D;
320            createView.format = format;
321            createView.components.r = VK_COMPONENT_SWIZZLE_R;
322            createView.components.g = VK_COMPONENT_SWIZZLE_G;
323            createView.components.b = VK_COMPONENT_SWIZZLE_B;
324            createView.components.a = VK_COMPONENT_SWIZZLE_A;
325            createView.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0,
326                                           1};
327            createView.flags = 0;
328            m_targetView.init(*m_device, createView);
329        }
330        return m_targetView.handle();
331    }
332
333    void SetLayout(VkCommandBufferObj *cmd_buf, VkImageAspectFlagBits aspect,
334                   VkImageLayout image_layout);
335    void SetLayout(VkImageAspectFlagBits aspect, VkImageLayout image_layout);
336
337    VkImageLayout layout() const { return m_descriptorImageInfo.imageLayout; }
338    uint32_t width() const { return extent().width; }
339    uint32_t height() const { return extent().height; }
340    VkDeviceObj *device() const { return m_device; }
341
342  protected:
343    VkDeviceObj *m_device;
344
345    vk_testing::ImageView m_targetView;
346    VkDescriptorImageInfo m_descriptorImageInfo;
347};
348
349class VkTextureObj : public VkImageObj {
350  public:
351    VkTextureObj(VkDeviceObj *device, uint32_t *colors = NULL);
352
353    VkDescriptorImageInfo m_imageInfo;
354
355  protected:
356    VkDeviceObj *m_device;
357    vk_testing::ImageView m_textureView;
358    VkDeviceSize m_rowPitch;
359};
360
361class VkSamplerObj : public vk_testing::Sampler {
362  public:
363    VkSamplerObj(VkDeviceObj *device);
364
365  protected:
366    VkDeviceObj *m_device;
367};
368
369class VkDescriptorSetObj : public vk_testing::DescriptorPool {
370  public:
371    VkDescriptorSetObj(VkDeviceObj *device);
372    ~VkDescriptorSetObj();
373
374    int AppendDummy();
375    int AppendBuffer(VkDescriptorType type,
376                     VkConstantBufferObj &constantBuffer);
377    int AppendSamplerTexture(VkSamplerObj *sampler, VkTextureObj *texture);
378    void CreateVKDescriptorSet(VkCommandBufferObj *commandBuffer);
379
380    VkDescriptorSet GetDescriptorSetHandle() const;
381    VkPipelineLayout GetPipelineLayout() const;
382    int GetTypeCounts() {return m_type_counts.size();}
383
384  protected:
385    VkDeviceObj *m_device;
386    vector<VkDescriptorPoolSize> m_type_counts;
387    int m_nextSlot;
388
389    vector<VkDescriptorImageInfo> m_imageSamplerDescriptors;
390    vector<VkWriteDescriptorSet> m_writes;
391
392    vk_testing::DescriptorSetLayout m_layout;
393    vk_testing::PipelineLayout m_pipeline_layout;
394    vk_testing::DescriptorSet *m_set = NULL;
395};
396
397class VkShaderObj : public vk_testing::ShaderModule {
398  public:
399    VkShaderObj(VkDeviceObj *device, const char *shaderText,
400                VkShaderStageFlagBits stage, VkRenderFramework *framework,
401                char const *name = "main");
402    VkPipelineShaderStageCreateInfo GetStageCreateInfo() const;
403
404  protected:
405    VkPipelineShaderStageCreateInfo stage_info;
406    VkShaderStageFlagBits m_stage;
407    char const *m_name;
408    VkDeviceObj *m_device;
409};
410
411class VkPipelineObj : public vk_testing::Pipeline {
412  public:
413    VkPipelineObj(VkDeviceObj *device);
414    void AddShader(VkShaderObj *shaderObj);
415    void AddVertexInputAttribs(VkVertexInputAttributeDescription *vi_attrib,
416                               int count);
417    void AddVertexInputBindings(VkVertexInputBindingDescription *vi_binding,
418                                int count);
419    void AddColorAttachment(uint32_t binding,
420                            const VkPipelineColorBlendAttachmentState *att);
421    void MakeDynamic(VkDynamicState state);
422
423    void AddColorAttachment() {
424        VkPipelineColorBlendAttachmentState att = {};
425        att.blendEnable = VK_FALSE;
426        att.colorWriteMask = 0xf;
427        AddColorAttachment(0, &att);
428    }
429
430    void SetDepthStencil(VkPipelineDepthStencilStateCreateInfo *);
431    void SetMSAA(VkPipelineMultisampleStateCreateInfo *ms_state);
432    void SetViewport(vector<VkViewport> viewports);
433    void SetScissor(vector<VkRect2D> scissors);
434    VkResult CreateVKPipeline(VkPipelineLayout layout,
435                              VkRenderPass render_pass);
436
437  protected:
438    VkPipelineVertexInputStateCreateInfo m_vi_state;
439    VkPipelineInputAssemblyStateCreateInfo m_ia_state;
440    VkPipelineRasterizationStateCreateInfo m_rs_state;
441    VkPipelineColorBlendStateCreateInfo m_cb_state;
442    VkPipelineDepthStencilStateCreateInfo m_ds_state;
443    VkPipelineViewportStateCreateInfo m_vp_state;
444    VkPipelineMultisampleStateCreateInfo m_ms_state;
445    vector<VkDynamicState> m_dynamic_state_enables;
446    vector<VkViewport> m_viewports;
447    vector<VkRect2D> m_scissors;
448    VkDeviceObj *m_device;
449    vector<VkShaderObj *> m_shaderObjs;
450    vector<int> m_vertexBufferBindings;
451    vector<VkPipelineColorBlendAttachmentState> m_colorAttachments;
452    int m_vertexBufferCount;
453};
454
455#endif // VKRENDERFRAMEWORK_H
456