layers: DrawState handles dynamic state set via PSO
authorTobin Ehlis <tobin@lunarg.com>
Tue, 29 Sep 2015 14:18:34 +0000 (08:18 -0600)
committerTobin Ehlis <tobin@lunarg.com>
Wed, 30 Sep 2015 17:18:13 +0000 (11:18 -0600)
For dynamic states flagged in PSO, consider them set at draw time.
Clarify various dynamic state error messages to make them more consistent with updated dynamic state API.
Add test for scissor not bound.

layers/draw_state.cpp
layers/draw_state.h
layers/vk_validation_layer_details.md

index 5a6d121182c80848e28e02c9232cacc70632958d..239a9b0ef460a7412b24599937396b3062978fba 100644 (file)
@@ -359,16 +359,17 @@ static PIPELINE_NODE* getPipeline(VkPipeline pipeline)
 // Validate state stored as flags at time of draw call
 static VkBool32 validate_draw_state_flags(GLOBAL_CB_NODE* pCB, VkBool32 indexedDraw) {
     VkBool32 result;
-    result = validate_status(pCB, CBSTATUS_NONE, CBSTATUS_VIEWPORT_SET, CBSTATUS_VIEWPORT_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_VIEWPORT_NOT_BOUND, "Viewport object not bound to this command buffer");
-    result |= validate_status(pCB, CBSTATUS_NONE, CBSTATUS_LINE_WIDTH_SET,   CBSTATUS_LINE_WIDTH_SET,   VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_LINE_WIDTH_NOT_BOUND,   "Line width object not bound to this command buffer");
-    result |= validate_status(pCB, CBSTATUS_NONE, CBSTATUS_DEPTH_BIAS_SET,   CBSTATUS_DEPTH_BIAS_SET,   VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_DEPTH_BIAS_NOT_BOUND,   "Depth bias object not bound to this command buffer");
-    result |= validate_status(pCB, CBSTATUS_COLOR_BLEND_WRITE_ENABLE, CBSTATUS_BLEND_SET,   CBSTATUS_BLEND_SET,   VK_DBG_REPORT_ERROR_BIT,  DRAWSTATE_BLEND_NOT_BOUND,   "Blend object not bound to this command buffer");
-    result |= validate_status(pCB, CBSTATUS_DEPTH_WRITE_ENABLE, CBSTATUS_DEPTH_BOUNDS_SET, CBSTATUS_DEPTH_BOUNDS_SET, VK_DBG_REPORT_ERROR_BIT,  DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND, "Depth bounds object not bound to this command buffer");
-    result |= validate_status(pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_READ_MASK_SET, CBSTATUS_STENCIL_READ_MASK_SET, VK_DBG_REPORT_ERROR_BIT,  DRAWSTATE_STENCIL_NOT_BOUND, "Stencil read mask not set on this command buffer");
-    result |= validate_status(pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_WRITE_MASK_SET, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DBG_REPORT_ERROR_BIT,  DRAWSTATE_STENCIL_NOT_BOUND, "Stencil write mask not set on this command buffer");
-    result |= validate_status(pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_REFERENCE_SET, CBSTATUS_STENCIL_REFERENCE_SET, VK_DBG_REPORT_ERROR_BIT,  DRAWSTATE_STENCIL_NOT_BOUND, "Stencil reference not set on this command buffer");
+    result = validate_status(pCB, CBSTATUS_NONE, CBSTATUS_VIEWPORT_SET, CBSTATUS_VIEWPORT_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_VIEWPORT_NOT_BOUND, "Dynamic viewport state not set for this command buffer");
+    result |= validate_status(pCB, CBSTATUS_NONE, CBSTATUS_SCISSOR_SET, CBSTATUS_SCISSOR_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic scissor state not set for this command buffer");
+    result |= validate_status(pCB, CBSTATUS_NONE, CBSTATUS_LINE_WIDTH_SET, CBSTATUS_LINE_WIDTH_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_LINE_WIDTH_NOT_BOUND, "Dynamic line width state not set for this command buffer");
+    result |= validate_status(pCB, CBSTATUS_NONE, CBSTATUS_DEPTH_BIAS_SET, CBSTATUS_DEPTH_BIAS_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_DEPTH_BIAS_NOT_BOUND, "Dynamic depth bias state not set for this command buffer");
+    result |= validate_status(pCB, CBSTATUS_COLOR_BLEND_WRITE_ENABLE, CBSTATUS_BLEND_SET, CBSTATUS_BLEND_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_BLEND_NOT_BOUND, "Dynamic blend object state not set for this command buffer");
+    result |= validate_status(pCB, CBSTATUS_DEPTH_WRITE_ENABLE, CBSTATUS_DEPTH_BOUNDS_SET, CBSTATUS_DEPTH_BOUNDS_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND, "Dynamic depth bounds state not set for this command buffer");
+    result |= validate_status(pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_READ_MASK_SET, CBSTATUS_STENCIL_READ_MASK_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil read mask state not set for this command buffer");
+    result |= validate_status(pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_WRITE_MASK_SET, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil write mask state not set for this command buffer");
+    result |= validate_status(pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_REFERENCE_SET, CBSTATUS_STENCIL_REFERENCE_SET, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil reference state not set for this command buffer");
     if (indexedDraw)
-        result |= validate_status(pCB, CBSTATUS_NONE, CBSTATUS_INDEX_BUFFER_BOUND, CBSTATUS_INDEX_BUFFER_BOUND, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_INDEX_BUFFER_NOT_BOUND, "Index buffer object not bound to this command buffer when Index Draw attempted");
+        result |= validate_status(pCB, CBSTATUS_NONE, CBSTATUS_INDEX_BUFFER_BOUND, CBSTATUS_INDEX_BUFFER_BOUND, VK_DBG_REPORT_ERROR_BIT, DRAWSTATE_INDEX_BUFFER_NOT_BOUND, "Index buffer object not bound to this command buffer when Indexed Draw attempted");
     return result;
 }
 // Validate overall state at the time of a draw call
@@ -469,7 +470,6 @@ static PIPELINE_NODE* initPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn
         memset((void*)pPipeline, 0, sizeof(PIPELINE_NODE));
     }
     // First init create info
-    // TODO : Validate that no create info is incorrectly replicated
     memcpy(&pPipeline->graphicsPipelineCI, pCreateInfo, sizeof(VkGraphicsPipelineCreateInfo));
 
     size_t bufferSize = 0;
@@ -509,7 +509,12 @@ static PIPELINE_NODE* initPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn
                 break;
         }
     }
-
+    // Copy over GraphicsPipelineCreateInfo structure embedded pointers
+    if (pCreateInfo->stageCount != 0) {
+        pPipeline->graphicsPipelineCI.pStages = new VkPipelineShaderStageCreateInfo[pCreateInfo->stageCount];
+        bufferSize =  pCreateInfo->stageCount * sizeof(VkPipelineShaderStageCreateInfo);
+        memcpy((void*)pPipeline->graphicsPipelineCI.pStages, pCreateInfo->pStages, bufferSize);
+    }
     if (pCreateInfo->pVertexInputState != NULL) {
         memcpy((void*)&pPipeline->vertexInputCI, pCreateInfo->pVertexInputState , sizeof(VkPipelineVertexInputStateCreateInfo));
         // Copy embedded ptrs
@@ -548,6 +553,10 @@ static PIPELINE_NODE* initPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn
         memcpy((void*)&pPipeline->msStateCI, pCreateInfo->pMultisampleState, sizeof(VkPipelineMultisampleStateCreateInfo));
         pPipeline->graphicsPipelineCI.pMultisampleState = &pPipeline->msStateCI;
     }
+    if (pCreateInfo->pDepthStencilState != NULL) {
+        memcpy((void*)&pPipeline->dsStateCI, pCreateInfo->pDepthStencilState, sizeof(VkPipelineDepthStencilStateCreateInfo));
+        pPipeline->graphicsPipelineCI.pDepthStencilState = &pPipeline->dsStateCI;
+    }
     if (pCreateInfo->pColorBlendState != NULL) {
         memcpy((void*)&pPipeline->cbStateCI, pCreateInfo->pColorBlendState, sizeof(VkPipelineColorBlendStateCreateInfo));
         // Copy embedded ptrs
@@ -560,16 +569,14 @@ static PIPELINE_NODE* initPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn
         }
         pPipeline->graphicsPipelineCI.pColorBlendState = &pPipeline->cbStateCI;
     }
-    if (pCreateInfo->pDepthStencilState != NULL) {
-        memcpy((void*)&pPipeline->dsStateCI, pCreateInfo->pDepthStencilState, sizeof(VkPipelineDepthStencilStateCreateInfo));
-        pPipeline->graphicsPipelineCI.pDepthStencilState = &pPipeline->dsStateCI;
-    }
-
-    // Copy over GraphicsPipelineCreateInfo structure embedded pointers
-    if (pCreateInfo->stageCount != 0) {
-        pPipeline->graphicsPipelineCI.pStages = new VkPipelineShaderStageCreateInfo[pCreateInfo->stageCount];
-        bufferSize =  pCreateInfo->stageCount * sizeof(VkPipelineShaderStageCreateInfo);
-        memcpy((void*)pPipeline->graphicsPipelineCI.pStages, pCreateInfo->pStages, bufferSize); 
+    if (pCreateInfo->pDynamicState != NULL) {
+        memcpy((void*)&pPipeline->dynStateCI, pCreateInfo->pDynamicState, sizeof(VkPipelineDynamicStateCreateInfo));
+        if (pPipeline->dynStateCI.dynamicStateCount) {
+            pPipeline->dynStateCI.pDynamicStates = new VkDynamicState[pPipeline->dynStateCI.dynamicStateCount];
+            bufferSize = pPipeline->dynStateCI.dynamicStateCount * sizeof(VkDynamicState);
+            memcpy((void*)pPipeline->dynStateCI.pDynamicStates, pCreateInfo->pDynamicState->pDynamicStates, bufferSize);
+        }
+        pPipeline->graphicsPipelineCI.pDynamicState = &pPipeline->dynStateCI;
     }
 
     return pPipeline;
@@ -593,6 +600,9 @@ static void deletePipelines()
         if ((*ii).second->pAttachments) {
             delete[] (*ii).second->pAttachments;
         }
+        if ((*ii).second->dynStateCI.dynamicStateCount != 0) {
+            delete[] (*ii).second->dynStateCI.pDynamicStates;
+        }
         delete (*ii).second;
     }
     pipelineMap.clear();
@@ -1126,7 +1136,7 @@ static void resetCB(const VkCmdBuffer cb)
         pCB->lastVtxBinding = MAX_BINDING;
     }
 }
-// Set PSO-related status bits for CB
+// Set PSO-related status bits for CB, including dynamic state set via PSO
 static void set_cb_pso_status(GLOBAL_CB_NODE* pCB, const PIPELINE_NODE* pPipe)
 {
     for (uint32_t i = 0; i < pPipe->cbStateCI.attachmentCount; i++) {
@@ -1137,10 +1147,46 @@ static void set_cb_pso_status(GLOBAL_CB_NODE* pCB, const PIPELINE_NODE* pPipe)
     if (pPipe->dsStateCI.depthWriteEnable) {
         pCB->status |= CBSTATUS_DEPTH_WRITE_ENABLE;
     }
-
     if (pPipe->dsStateCI.stencilTestEnable) {
         pCB->status |= CBSTATUS_STENCIL_TEST_ENABLE;
     }
+    if (pPipe->dynStateCI.dynamicStateCount) {
+        // Account for any dynamic state set via this PSO
+        for (uint32_t i=0; i < pPipe->dynStateCI.dynamicStateCount; i++) {
+            switch (pPipe->dynStateCI.pDynamicStates[i]) {
+                case VK_DYNAMIC_STATE_VIEWPORT:
+                    pCB->status |= CBSTATUS_VIEWPORT_SET;
+                    break;
+                case VK_DYNAMIC_STATE_SCISSOR:
+                    pCB->status |= CBSTATUS_SCISSOR_SET;
+                    break;
+                case VK_DYNAMIC_STATE_LINE_WIDTH:
+                    pCB->status |= CBSTATUS_LINE_WIDTH_SET;
+                    break;
+                case VK_DYNAMIC_STATE_DEPTH_BIAS:
+                    pCB->status |= CBSTATUS_DEPTH_BIAS_SET;
+                    break;
+                case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
+                    pCB->status |= CBSTATUS_BLEND_SET;
+                    break;
+                case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
+                    pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET;
+                    break;
+                case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
+                    pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET;
+                    break;
+                case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
+                    pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET;
+                    break;
+                case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
+                    pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET;
+                    break;
+                default:
+                    // TODO : Flag error here
+                    break;
+            }
+        }
+    }
 }
 // Print the last bound Gfx Pipeline
 static VkBool32 printPipeline(const VkCmdBuffer cb)
index 1641f8a6358d07321f53b4be0b62fbe900051681..c84eb2e77511cd1d21589e99ee67256cbb4c4ec7 100644 (file)
@@ -52,13 +52,14 @@ typedef enum _DRAW_STATE_ERROR
     DRAWSTATE_NO_BEGIN_CMD_BUFFER,              // Binding cmds or calling End on CB that never had vkBeginCommandBuffer() called on it
     DRAWSTATE_CMD_BUFFER_SINGLE_SUBMIT_VIOLATION, // Cmd Buffer created with VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT flag is submitted multiple times
     DRAWSTATE_INVALID_SECONDARY_CMD_BUFFER,     // vkCmdExecuteCommands() called with a primary cmdBuffer in pCmdBuffers array
-    DRAWSTATE_VIEWPORT_NOT_BOUND,               // Draw submitted with no viewport state object bound
-    DRAWSTATE_LINE_WIDTH_NOT_BOUND,             // Draw submitted with no line width state object bound
-    DRAWSTATE_DEPTH_BIAS_NOT_BOUND,             // Draw submitted with no depth bias state object bound
-    DRAWSTATE_BLEND_NOT_BOUND,                  // Draw submitted with no blend state object bound when color write enabled
-    DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND,           // Draw submitted with no depth bounds state object bound when depth enabled
-    DRAWSTATE_STENCIL_NOT_BOUND,                // Draw submitted with no stencil state object bound when stencil enabled
-    DRAWSTATE_INDEX_BUFFER_NOT_BOUND,           // Draw submitted with no depth-stencil state object bound when depth write enabled
+    DRAWSTATE_VIEWPORT_NOT_BOUND,               // Draw submitted with no viewport state bound
+    DRAWSTATE_SCISSOR_NOT_BOUND,                // Draw submitted with no scissor state bound
+    DRAWSTATE_LINE_WIDTH_NOT_BOUND,             // Draw submitted with no line width state bound
+    DRAWSTATE_DEPTH_BIAS_NOT_BOUND,             // Draw submitted with no depth bias state bound
+    DRAWSTATE_BLEND_NOT_BOUND,                  // Draw submitted with no blend state bound when color write enabled
+    DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND,           // Draw submitted with no depth bounds state bound when depth enabled
+    DRAWSTATE_STENCIL_NOT_BOUND,                // Draw submitted with no stencil state bound when stencil enabled
+    DRAWSTATE_INDEX_BUFFER_NOT_BOUND,           // Draw submitted with no depth-stencil state bound when depth write enabled
     DRAWSTATE_PIPELINE_LAYOUT_MISMATCH,         // Draw submitted PSO Pipeline layout that doesn't match layout from BindDescriptorSets
     DRAWSTATE_INVALID_RENDERPASS,               // Use of a NULL or otherwise invalid RenderPass object
     DRAWSTATE_INVALID_RENDERPASS_CMD,           // Invalid cmd submitted while a RenderPass is active
@@ -101,6 +102,7 @@ typedef struct _PIPELINE_NODE {
     VkPipelineMultisampleStateCreateInfo    msStateCI;
     VkPipelineColorBlendStateCreateInfo     cbStateCI;
     VkPipelineDepthStencilStateCreateInfo   dsStateCI;
+    VkPipelineDynamicStateCreateInfo        dynStateCI;
     VkPipelineShaderStageCreateInfo         vsCI;
     VkPipelineShaderStageCreateInfo         tcsCI;
     VkPipelineShaderStageCreateInfo         tesCI;
@@ -110,7 +112,6 @@ typedef struct _PIPELINE_NODE {
     VkComputePipelineCreateInfo          computePipelineCI;
     // Flag of which shader stages are active for this pipeline
     uint32_t                             active_shaders;
-    VkGraphicsPipelineCreateInfo*        pCreateTree;       // Ptr to shadow of data in create tree
     // Vtx input info (if any)
     uint32_t                             vtxBindingCount;   // number of bindings
     VkVertexInputBindingDescription*     pVertexBindingDescriptions;
index c6e7a679fda8c6795fbfd409c20bbc24ec6e4182..80081328347773d00bfc9e1ce6dfd7172e2a4a50 100644 (file)
@@ -34,6 +34,7 @@ The DrawState layer tracks state leading into Draw cmds. This includes the Pipel
 | DS Update Type | Verifies that structs in DS Update tree are properly created, currenly valid, and of the right type | INVALID_UPDATE_STRUCT | vkUpdateDescriptorSets | InvalidDSUpdateStruct | NA |
 | MSAA Sample Count | Verifies that Pipeline, RenderPass, and Subpass sample counts are consistent | NUM_SAMPLES_MISMATCH | vkCmdBindPipeline vkCmdBeginRenderPass vkCmdNextSubpass | NumSamplesMismatch | NA |
 | Dynamic Viewport State Binding | Verify that viewport dynamic state bound to Cmd Buffer at Draw time | VIEWPORT_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | ViewportStateNotBound | NA |
+| Dynamic Scissor State Binding | Verify that scissor dynamic state bound to Cmd Buffer at Draw time | SCISSOR_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | ScissorStateNotBound | NA |
 | Dynamic Line Width State Binding | Verify that line width dynamic state bound to Cmd Buffer at when required (TODO : Verify when this is) | LINE_WIDTH_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | TODO | Verify this check and Write targeted test |
 | Dynamic Depth Bias State Binding | Verify that depth bias dynamic state bound when depth enabled | DEPTH_BIAS_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | TODO | Verify this check and Write targeted test |
 | Dynamic Blend State Binding | Verify that blend dynamic state bound when color blend enabled | BLEND_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | TODO | Verify this check and Write targeted test |
@@ -75,6 +76,7 @@ Additional checks to be added to DrawState
  29. Flag an error if CmdBuffer has Begin called while it's being constructed - this is not a reset, this is a violation
  30. At PSO creation time, there is no case when NOT including a FS should flag an error since there exist dynamic state configurations that can be set to cause a FS to not be required. Instead, in the case when no FS is in the PSO, validation should detect at runtime if dynamic state will require a FS, and in those case issue a runtime warning about undefined behavior. (see bug https://cvs.khronos.org/bugzilla/show_bug.cgi?id=14429)
  31. Error if a cmdbuffer is submitted on a queue whose family doesn't match the family of the pool from which it was created.
+ 32. Update Gfx Pipe Create Info shadowing to remove new/delete and instead use unique_ptrs for auto clean-up
 
 ## ParamChecker
 
@@ -222,6 +224,7 @@ The ObjectTracker layer maintains a record of all Vulkan objects. It flags error
  7. Verify cube array VkImageView objects use subresourceRange.arraySize (or effective arraySize when VK_REMAINING_ARRAY_SLICES is specified) that is a multiple of 6. 
  8. Make object maps specific to instance and device.  Objects may only be used with matching instance or device.
  9. Use reference counting for non-dispatchable objects.  Multiple object creation calls may return identical handles.
+ 10. Update codegen for destroy_obj & validate_obj to generate all of the correct signatures and use the generated code
 
 ## Threading