Buffer fix for VkProgram caching
When caching VkPrograms, we can end up with situations where we
overwrite uniform buffers while they're in use (or being prepared for
use) in the command buffer. This fix will address that. This also
addresses the rare but similar case of overwriting vertex or index
buffers when they're in flight.
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1774963003
Review URL: https://codereview.chromium.org/1774963003
diff --git a/src/gpu/vk/GrVkProgramDataManager.cpp b/src/gpu/vk/GrVkProgramDataManager.cpp
index f189097..e798cd7 100644
--- a/src/gpu/vk/GrVkProgramDataManager.cpp
+++ b/src/gpu/vk/GrVkProgramDataManager.cpp
@@ -14,7 +14,9 @@
uint32_t vertexUniformSize,
uint32_t fragmentUniformSize)
: fVertexUniformSize(vertexUniformSize)
- , fFragmentUniformSize(fragmentUniformSize) {
+ , fFragmentUniformSize(fragmentUniformSize)
+ , fVertexUniformsDirty(false)
+ , fFragmentUniformsDirty(false) {
fVertexUniformData.reset(vertexUniformSize);
fFragmentUniformData.reset(fragmentUniformSize);
int count = uniforms.count();
@@ -38,19 +40,27 @@
}
}
+void* GrVkProgramDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
+ void* buffer;
+ if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
+ buffer = fVertexUniformData.get();
+ fVertexUniformsDirty = true;
+ }
+ else {
+ SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
+ buffer = fFragmentUniformData.get();
+ fFragmentUniformsDirty = true;
+ }
+ buffer = static_cast<char*>(buffer)+uni.fOffset;
+ return buffer;
+}
+
void GrVkProgramDataManager::set1f(UniformHandle u, float v0) const {
const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kFloat_GrSLType);
SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
- void* buffer;
- if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
- buffer = fVertexUniformData.get();
- } else {
- SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
- buffer = fFragmentUniformData.get();
- }
- buffer = static_cast<char*>(buffer) + uni.fOffset;
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4);
memcpy(buffer, &v0, sizeof(float));
}
@@ -65,14 +75,7 @@
(1 == arrayCount && GrGLSLShaderVar::kNonArray == uni.fArrayCount));
SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
- void* buffer;
- if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
- buffer = fVertexUniformData.get();
- } else {
- SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
- buffer = fFragmentUniformData.get();
- }
- buffer = static_cast<char*>(buffer) + uni.fOffset;
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4);
for (int i = 0; i < arrayCount; ++i) {
const float* curVec = &v[i];
@@ -86,14 +89,7 @@
SkASSERT(uni.fType == kVec2f_GrSLType);
SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
- void* buffer;
- if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
- buffer = fVertexUniformData.get();
- } else {
- SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
- buffer = fFragmentUniformData.get();
- }
- buffer = static_cast<char*>(buffer) + uni.fOffset;
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4);
float v[2] = { v0, v1 };
memcpy(buffer, v, 2 * sizeof(float));
@@ -109,14 +105,7 @@
(1 == arrayCount && GrGLSLShaderVar::kNonArray == uni.fArrayCount));
SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
- void* buffer;
- if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
- buffer = fVertexUniformData.get();
- } else {
- SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
- buffer = fFragmentUniformData.get();
- }
- buffer = static_cast<char*>(buffer) + uni.fOffset;
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4);
for (int i = 0; i < arrayCount; ++i) {
const float* curVec = &v[2 * i];
@@ -130,14 +119,7 @@
SkASSERT(uni.fType == kVec3f_GrSLType);
SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
- void* buffer;
- if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
- buffer = fVertexUniformData.get();
- } else {
- SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
- buffer = fFragmentUniformData.get();
- }
- buffer = static_cast<char*>(buffer) + uni.fOffset;
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4);
float v[3] = { v0, v1, v2 };
memcpy(buffer, v, 3 * sizeof(float));
@@ -153,14 +135,7 @@
(1 == arrayCount && GrGLSLShaderVar::kNonArray == uni.fArrayCount));
SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
- void* buffer;
- if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
- buffer = fVertexUniformData.get();
- } else {
- SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
- buffer = fFragmentUniformData.get();
- }
- buffer = static_cast<char*>(buffer) + uni.fOffset;
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4);
for (int i = 0; i < arrayCount; ++i) {
const float* curVec = &v[3 * i];
@@ -174,14 +149,7 @@
SkASSERT(uni.fType == kVec4f_GrSLType);
SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
- void* buffer;
- if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
- buffer = fVertexUniformData.get();
- } else {
- SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
- buffer = fFragmentUniformData.get();
- }
- buffer = static_cast<char*>(buffer) + uni.fOffset;
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4);
float v[4] = { v0, v1, v2, v3 };
memcpy(buffer, v, 4 * sizeof(float));
@@ -197,14 +165,7 @@
(1 == arrayCount && GrGLSLShaderVar::kNonArray == uni.fArrayCount));
SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
- void* buffer;
- if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
- buffer = fVertexUniformData.get();
- } else {
- SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
- buffer = fFragmentUniformData.get();
- }
- buffer = static_cast<char*>(buffer) + uni.fOffset;
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
SkASSERT(sizeof(float) == 4);
memcpy(buffer, v, arrayCount * 4 * sizeof(float));
}
@@ -236,8 +197,8 @@
template<int N> struct set_uniform_matrix;
template<int N> inline void GrVkProgramDataManager::setMatrices(UniformHandle u,
- int arrayCount,
- const float matrices[]) const {
+ int arrayCount,
+ const float matrices[]) const {
const Uniform& uni = fUniforms[u.toIndex()];
SkASSERT(uni.fType == kMat22f_GrSLType + (N - 2));
SkASSERT(arrayCount > 0);
@@ -248,9 +209,11 @@
void* buffer;
if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
buffer = fVertexUniformData.get();
+ fVertexUniformsDirty = true;
} else {
SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
buffer = fFragmentUniformData.get();
+ fFragmentUniformsDirty = true;
}
set_uniform_matrix<N>::set(buffer, uni.fOffset, arrayCount, matrices);
@@ -283,7 +246,7 @@
void GrVkProgramDataManager::uploadUniformBuffers(const GrVkGpu* gpu,
GrVkUniformBuffer* vertexBuffer,
GrVkUniformBuffer* fragmentBuffer) const {
- if (vertexBuffer) {
+ if (vertexBuffer && fVertexUniformsDirty) {
vertexBuffer->addMemoryBarrier(gpu,
VK_ACCESS_UNIFORM_READ_BIT,
VK_ACCESS_HOST_WRITE_BIT,
@@ -291,9 +254,10 @@
VK_PIPELINE_STAGE_HOST_BIT,
false);
SkAssertResult(vertexBuffer->updateData(gpu, fVertexUniformData.get(), fVertexUniformSize));
+ fVertexUniformsDirty = false;
}
- if (fragmentBuffer) {
+ if (fragmentBuffer && fFragmentUniformsDirty) {
fragmentBuffer->addMemoryBarrier(gpu,
VK_ACCESS_UNIFORM_READ_BIT,
VK_ACCESS_HOST_WRITE_BIT,
@@ -302,6 +266,7 @@
false);
SkAssertResult(fragmentBuffer->updateData(gpu, fFragmentUniformData.get(),
fFragmentUniformSize));
+ fFragmentUniformsDirty = false;
}
}