1164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel/*
2164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel* Copyright 2016 Google Inc.
3164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel*
4164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel* Use of this source code is governed by a BSD-style license that can be
5164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel* found in the LICENSE file.
6164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel*/
7164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkProgram.h"
9164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrPipeline.h"
11164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkCommandBuffer.h"
12164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkDescriptorPool.h"
13164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkGpu.h"
14164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkImageView.h"
15164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkMemory.h"
16164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkPipeline.h"
17164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkSampler.h"
18164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTexture.h"
19164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkUniformBuffer.h"
20164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "glsl/GrGLSLFragmentProcessor.h"
21164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "glsl/GrGLSLGeometryProcessor.h"
22164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "glsl/GrGLSLXferProcessor.h"
23164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
24164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkProgram::GrVkProgram(GrVkGpu* gpu,
25164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         GrVkPipeline* pipeline,
26164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VkPipelineLayout layout,
27164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VkDescriptorSetLayout dsLayout[2],
28164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         GrVkDescriptorPool* descriptorPool,
29164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VkDescriptorSet descriptorSets[2],
30164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         const BuiltinUniformHandles& builtinUniformHandles,
31164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         const UniformInfoArray& uniforms,
32164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         uint32_t vertexUniformSize,
33164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         uint32_t fragmentUniformSize,
34164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         uint32_t numSamplers,
35164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         GrGLSLPrimitiveProcessor* geometryProcessor,
36164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         GrGLSLXferProcessor* xferProcessor,
37164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         const GrGLSLFragProcs& fragmentProcessors)
38164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    : fDescriptorPool(descriptorPool)
39164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fPipeline(pipeline)
40164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fPipelineLayout(layout)
41164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fBuiltinUniformHandles(builtinUniformHandles)
42164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fGeometryProcessor(geometryProcessor)
43164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fXferProcessor(xferProcessor)
44164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fFragmentProcessors(fragmentProcessors)
45164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fProgramDataManager(uniforms, vertexUniformSize, fragmentUniformSize) {
46164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fSamplers.setReserve(numSamplers);
47164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fTextureViews.setReserve(numSamplers);
48164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fTextures.setReserve(numSamplers);
49164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
50164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memcpy(fDSLayout, dsLayout, 2 * sizeof(VkDescriptorSetLayout));
51164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memcpy(fDescriptorSets, descriptorSets, 2 * sizeof(VkDescriptorSetLayout));
52164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
53164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fVertexUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, vertexUniformSize, true));
54164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fFragmentUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, fragmentUniformSize, true));
55164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
56164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#ifdef SK_DEBUG
57164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fNumSamplers = numSamplers;
58164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
59164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
60164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
61164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkProgram::~GrVkProgram() {
62164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Must of freed all GPU resources before this is destroyed
63164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!fPipeline);
64164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!fDescriptorPool);
65164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!fPipelineLayout);
66164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!fDSLayout[0]);
67164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!fDSLayout[1]);
68164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!fSamplers.count());
69164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!fTextureViews.count());
70164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!fTextures.count());
71164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
72164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
73164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkProgram::freeTempResources(const GrVkGpu* gpu) {
74164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fSamplers.count(); ++i) {
75164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fSamplers[i]->unref(gpu);
76164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
77164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fSamplers.rewind();
78164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
79164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fTextureViews.count(); ++i) {
80164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            fTextureViews[i]->unref(gpu);
81164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
82164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fTextureViews.rewind();
83164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
84164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fTextures.count(); ++i) {
85164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            fTextures[i]->unref(gpu);
86164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
87164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fTextures.rewind();
88164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
89164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
90164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkProgram::freeGPUResources(const GrVkGpu* gpu) {
91164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fPipeline) {
92164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fPipeline->unref(gpu);
93164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fPipeline = nullptr;
94164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
95164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fDescriptorPool) {
96164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fDescriptorPool->unref(gpu);
97164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fDescriptorPool = nullptr;
98164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
99164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fPipelineLayout) {
100164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(),
101164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                             fPipelineLayout,
102164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                             nullptr));
103164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fPipelineLayout = nullptr;
104164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
105164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
106164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fDSLayout[0]) {
107164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDSLayout[0],
108164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                  nullptr));
109164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fDSLayout[0] = nullptr;
110164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
111164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fDSLayout[1]) {
112164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDSLayout[1],
113164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                  nullptr));
114164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fDSLayout[1] = nullptr;
115164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
116164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
117164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fVertexUniformBuffer) {
118164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fVertexUniformBuffer->release(gpu);
119164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
120164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
121164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fFragmentUniformBuffer) {
122164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fFragmentUniformBuffer->release(gpu);
123164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
124164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->freeTempResources(gpu);
125164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
126164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
127164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkProgram::abandonGPUResources() {
128164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fPipeline->unrefAndAbandon();
129164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fPipeline = nullptr;
130164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fDescriptorPool->unrefAndAbandon();
131164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fDescriptorPool = nullptr;
132164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fPipelineLayout = nullptr;
133164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fDSLayout[0] = nullptr;
134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fDSLayout[1] = nullptr;
135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fVertexUniformBuffer->abandon();
137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fFragmentUniformBuffer->abandon();
138164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fSamplers.count(); ++i) {
140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fSamplers[i]->unrefAndAbandon();
141164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
142164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fSamplers.rewind();
143164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
144164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fTextureViews.count(); ++i) {
145164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fTextureViews[i]->unrefAndAbandon();
146164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fTextureViews.rewind();
148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fTextures.count(); ++i) {
150164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fTextures[i]->unrefAndAbandon();
151164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
152164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fTextures.rewind();
153164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
154164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
155164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic void append_texture_bindings(const GrProcessor& processor,
156164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    SkTArray<const GrTextureAccess*>* textureBindings) {
157164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (int numTextures = processor.numTextures()) {
158164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrTextureAccess** bindings = textureBindings->push_back_n(numTextures);
159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        int i = 0;
160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        do {
161164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            bindings[i] = &processor.textureAccess(i);
162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } while (++i < numTextures);
163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkProgram::setData(const GrVkGpu* gpu,
167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                          const GrPrimitiveProcessor& primProc,
168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                          const GrPipeline& pipeline) {
169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This is here to protect against someone calling setData multiple times in a row without
170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // freeing the tempData between calls.
171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->freeTempResources(gpu);
172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->setRenderTargetState(pipeline);
174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkSTArray<8, const GrTextureAccess*> textureBindings;
176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
177164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fGeometryProcessor->setData(fProgramDataManager, primProc);
178164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    append_texture_bindings(primProc, &textureBindings);
179164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
180164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fFragmentProcessors.count(); ++i) {
181164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i);
182164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fFragmentProcessors[i]->setData(fProgramDataManager, processor);
183164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fGeometryProcessor->setTransformData(primProc, fProgramDataManager, i,
184164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             processor.coordTransforms());
185164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        append_texture_bindings(processor, &textureBindings);
186164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
188164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fXferProcessor->setData(fProgramDataManager, pipeline.getXferProcessor());
189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    append_texture_bindings(pipeline.getXferProcessor(), &textureBindings);
190164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
191164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->writeUniformBuffers(gpu);
192164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->writeSamplers(gpu, textureBindings);
194164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
195164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
196164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkProgram::writeUniformBuffers(const GrVkGpu* gpu) {
197164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fProgramDataManager.uploadUniformBuffers(gpu, fVertexUniformBuffer, fFragmentUniformBuffer);
198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkWriteDescriptorSet descriptorWrites[2];
200164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(descriptorWrites, 0, 2 * sizeof(VkWriteDescriptorSet));
201164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    uint32_t firstUniformWrite = 0;
203164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    uint32_t uniformBindingUpdateCount = 0;
204164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
205164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Vertex Uniform Buffer
206164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fVertexUniformBuffer.get()) {
207164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        ++uniformBindingUpdateCount;
208164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkDescriptorBufferInfo vertBufferInfo;
209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&vertBufferInfo, 0, sizeof(VkDescriptorBufferInfo));
210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vertBufferInfo.buffer = fVertexUniformBuffer->buffer();
211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vertBufferInfo.offset = 0;
212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vertBufferInfo.range = fVertexUniformBuffer->size();
213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
215164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].pNext = nullptr;
216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].dstSet = fDescriptorSets[1];
217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].dstBinding = GrVkUniformHandler::kVertexBinding;
218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].dstArrayElement = 0;
219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].descriptorCount = 1;
220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
221164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].pImageInfo = nullptr;
222164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].pBufferInfo = &vertBufferInfo;
223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[0].pTexelBufferView = nullptr;
224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
225164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Fragment Uniform Buffer
227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fFragmentUniformBuffer.get()) {
228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (0 == uniformBindingUpdateCount) {
229164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            firstUniformWrite = 1;
230164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
231164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        ++uniformBindingUpdateCount;
232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkDescriptorBufferInfo fragBufferInfo;
233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&fragBufferInfo, 0, sizeof(VkDescriptorBufferInfo));
234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fragBufferInfo.buffer = fFragmentUniformBuffer->buffer();
235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fragBufferInfo.offset = 0;
236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fragBufferInfo.range = fFragmentUniformBuffer->size();
237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].pNext = nullptr;
240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].dstSet = fDescriptorSets[1];
241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].dstBinding = GrVkUniformHandler::kFragBinding;;
242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].dstArrayElement = 0;
243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].descriptorCount = 1;
244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].pImageInfo = nullptr;
246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].pBufferInfo = &fragBufferInfo;
247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        descriptorWrites[1].pTexelBufferView = nullptr;
248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (uniformBindingUpdateCount) {
251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            uniformBindingUpdateCount,
253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            &descriptorWrites[firstUniformWrite],
254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            0, nullptr));
255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkProgram::writeSamplers(const GrVkGpu* gpu,
259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkTArray<const GrTextureAccess*>& textureBindings) {
260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fNumSamplers == textureBindings.count());
261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < textureBindings.count(); ++i) {
263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fSamplers.push(GrVkSampler::Create(gpu, *textureBindings[i]));
264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GrVkTexture* texture = static_cast<GrVkTexture*>(textureBindings[i]->getTexture());
266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrVkImage::Resource* textureResource = texture->resource();
268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        textureResource->ref();
269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fTextures.push(textureResource);
270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrVkImageView* textureView = texture->textureView();
272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        textureView->ref();
273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fTextureViews.push(textureView);
274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // Change texture layout so it can be read in shader
276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkImageLayout layout = texture->currentLayout();
277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        texture->setImageLayout(gpu,
282164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
283164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                srcAccessMask,
284164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                dstAccessMask,
285164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                srcStageMask,
286164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                dstStageMask,
287164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                false);
288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkDescriptorImageInfo imageInfo;
290164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        imageInfo.sampler = fSamplers[i]->sampler();
292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        imageInfo.imageView = texture->textureView()->imageView();
293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkWriteDescriptorSet writeInfo;
296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.pNext = nullptr;
299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kSamplerDescSet];
300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.dstBinding = i;
301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.dstArrayElement = 0;
302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.descriptorCount = 1;
303164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
304164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.pImageInfo = &imageInfo;
305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.pBufferInfo = nullptr;
306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        writeInfo.pTexelBufferView = nullptr;
307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            1,
310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            &writeInfo,
311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            0,
312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            nullptr));
313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkProgram::setRenderTargetState(const GrPipeline& pipeline) {
317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
319164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fRenderTargetState.fRenderTargetSize.fHeight != pipeline.getRenderTarget()->height()) {
320164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  SkIntToScalar(pipeline.getRenderTarget()->height()));
322164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
323164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
324164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // set RT adjustment
325164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrRenderTarget* rt = pipeline.getRenderTarget();
326164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkISize size;
327164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size.set(rt->width(), rt->height());
328164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
329164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fRenderTargetState.fRenderTargetOrigin != rt->origin() ||
330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fRenderTargetState.fRenderTargetSize != size) {
331164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fRenderTargetState.fRenderTargetSize = size;
332164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fRenderTargetState.fRenderTargetOrigin = rt->origin();
333164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
334164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        float rtAdjustmentVec[4];
335164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
336164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
337164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
338164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
339164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
340164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkProgram::bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) {
341164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    commandBuffer->bindPipeline(gpu, fPipeline);
342164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, 0, 2, fDescriptorSets, 0,
343164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                      nullptr);
344164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
345164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
346164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkProgram::addUniformResources(GrVkCommandBuffer& commandBuffer) {
347164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if 1
348164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    commandBuffer.addResource(fDescriptorPool);
349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fVertexUniformBuffer.get()) {
350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        commandBuffer.addResource(fVertexUniformBuffer->resource());
351164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
352164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fFragmentUniformBuffer.get()) {
353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        commandBuffer.addResource(fFragmentUniformBuffer->resource());
354164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
355164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fSamplers.count(); ++i) {
356164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        commandBuffer.addResource(fSamplers[i]);
357164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
358164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
359164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fTextureViews.count(); ++i) {
360164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        commandBuffer.addResource(fTextureViews[i]);
361164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
362164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (int i = 0; i < fTextures.count(); ++i) {
364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        commandBuffer.addResource(fTextures[i]);
365164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
367164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
368