Rework dummy image handling to avoid RTX HDR driver bug
As a side effect, it avoids useless allocations and uploads of a zeroed memory buffer to clear the dummy image textures.
This commit is contained in:
@@ -125,6 +125,9 @@ namespace platf::dxgi {
|
||||
// the first successful capture of a desktop frame
|
||||
bool dummy = false;
|
||||
|
||||
// Set to true if the image is blank (contains no content at all, including a cursor)
|
||||
bool blank = true;
|
||||
|
||||
// Unique identifier for this image
|
||||
uint32_t id = 0;
|
||||
|
||||
@@ -382,39 +385,41 @@ namespace platf::dxgi {
|
||||
}
|
||||
|
||||
auto &img = (img_d3d_t &) img_base;
|
||||
auto &img_ctx = img_ctx_map[img.id];
|
||||
if (!img.blank) {
|
||||
auto &img_ctx = img_ctx_map[img.id];
|
||||
|
||||
// Open the shared capture texture with our ID3D11Device
|
||||
if (initialize_image_context(img, img_ctx)) {
|
||||
return -1;
|
||||
// Open the shared capture texture with our ID3D11Device
|
||||
if (initialize_image_context(img, img_ctx)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Acquire encoder mutex to synchronize with capture code
|
||||
auto status = img_ctx.encoder_mutex->AcquireSync(0, INFINITE);
|
||||
if (status != S_OK) {
|
||||
BOOST_LOG(error) << "Failed to acquire encoder mutex [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return -1;
|
||||
}
|
||||
|
||||
device_ctx->OMSetRenderTargets(1, &nv12_Y_rt, nullptr);
|
||||
device_ctx->VSSetShader(scene_vs.get(), nullptr, 0);
|
||||
device_ctx->PSSetShader(img.format == DXGI_FORMAT_R16G16B16A16_FLOAT ? convert_Y_fp16_ps.get() : convert_Y_ps.get(), nullptr, 0);
|
||||
device_ctx->RSSetViewports(1, &outY_view);
|
||||
device_ctx->PSSetShaderResources(0, 1, &img_ctx.encoder_input_res);
|
||||
device_ctx->Draw(3, 0);
|
||||
|
||||
device_ctx->OMSetRenderTargets(1, &nv12_UV_rt, nullptr);
|
||||
device_ctx->VSSetShader(convert_UV_vs.get(), nullptr, 0);
|
||||
device_ctx->PSSetShader(img.format == DXGI_FORMAT_R16G16B16A16_FLOAT ? convert_UV_fp16_ps.get() : convert_UV_ps.get(), nullptr, 0);
|
||||
device_ctx->RSSetViewports(1, &outUV_view);
|
||||
device_ctx->Draw(3, 0);
|
||||
|
||||
// Release encoder mutex to allow capture code to reuse this image
|
||||
img_ctx.encoder_mutex->ReleaseSync(0);
|
||||
|
||||
ID3D11ShaderResourceView *emptyShaderResourceView = nullptr;
|
||||
device_ctx->PSSetShaderResources(0, 1, &emptyShaderResourceView);
|
||||
}
|
||||
|
||||
// Acquire encoder mutex to synchronize with capture code
|
||||
auto status = img_ctx.encoder_mutex->AcquireSync(0, INFINITE);
|
||||
if (status != S_OK) {
|
||||
BOOST_LOG(error) << "Failed to acquire encoder mutex [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return -1;
|
||||
}
|
||||
|
||||
device_ctx->OMSetRenderTargets(1, &nv12_Y_rt, nullptr);
|
||||
device_ctx->VSSetShader(scene_vs.get(), nullptr, 0);
|
||||
device_ctx->PSSetShader(img.format == DXGI_FORMAT_R16G16B16A16_FLOAT ? convert_Y_fp16_ps.get() : convert_Y_ps.get(), nullptr, 0);
|
||||
device_ctx->RSSetViewports(1, &outY_view);
|
||||
device_ctx->PSSetShaderResources(0, 1, &img_ctx.encoder_input_res);
|
||||
device_ctx->Draw(3, 0);
|
||||
|
||||
device_ctx->OMSetRenderTargets(1, &nv12_UV_rt, nullptr);
|
||||
device_ctx->VSSetShader(convert_UV_vs.get(), nullptr, 0);
|
||||
device_ctx->PSSetShader(img.format == DXGI_FORMAT_R16G16B16A16_FLOAT ? convert_UV_fp16_ps.get() : convert_UV_ps.get(), nullptr, 0);
|
||||
device_ctx->RSSetViewports(1, &outUV_view);
|
||||
device_ctx->Draw(3, 0);
|
||||
|
||||
// Release encoder mutex to allow capture code to reuse this image
|
||||
img_ctx.encoder_mutex->ReleaseSync(0);
|
||||
|
||||
ID3D11ShaderResourceView *emptyShaderResourceView = nullptr;
|
||||
device_ctx->PSSetShaderResources(0, 1, &emptyShaderResourceView);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1144,6 +1149,9 @@ namespace platf::dxgi {
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
// Clear the blank flag now that we're ready to capture into the image
|
||||
d3d_img->blank = false;
|
||||
|
||||
return { std::move(d3d_img), std::move(lock_helper) };
|
||||
};
|
||||
|
||||
@@ -1289,15 +1297,14 @@ namespace platf::dxgi {
|
||||
// Clear the image if it has been used as a dummy.
|
||||
// It can have the mouse cursor blended onto it.
|
||||
auto old_d3d_img = (img_d3d_t *) img_out.get();
|
||||
bool reclear_dummy = old_d3d_img->dummy && old_d3d_img->capture_texture;
|
||||
bool reclear_dummy = !old_d3d_img->blank && old_d3d_img->capture_texture;
|
||||
|
||||
auto [d3d_img, lock] = get_locked_d3d_img(img_out, true);
|
||||
if (!d3d_img) return capture_e::error;
|
||||
|
||||
if (reclear_dummy) {
|
||||
auto dummy_data = std::make_unique<std::uint8_t[]>(d3d_img->row_pitch * d3d_img->height);
|
||||
std::fill_n(dummy_data.get(), d3d_img->row_pitch * d3d_img->height, 0);
|
||||
device_ctx->UpdateSubresource(d3d_img->capture_texture.get(), 0, nullptr, dummy_data.get(), d3d_img->row_pitch, 0);
|
||||
const float rgb_black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
device_ctx->ClearRenderTargetView(d3d_img->capture_rt.get(), rgb_black);
|
||||
}
|
||||
|
||||
if (blend_mouse_cursor_flag) {
|
||||
@@ -1409,6 +1416,7 @@ namespace platf::dxgi {
|
||||
img->width = width_before_rotation;
|
||||
img->height = height_before_rotation;
|
||||
img->id = next_image_id++;
|
||||
img->blank = true;
|
||||
|
||||
return img;
|
||||
}
|
||||
@@ -1456,20 +1464,7 @@ namespace platf::dxgi {
|
||||
t.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||
t.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
|
||||
HRESULT status;
|
||||
if (dummy) {
|
||||
auto dummy_data = std::make_unique<std::uint8_t[]>(img->row_pitch * img->height);
|
||||
std::fill_n(dummy_data.get(), img->row_pitch * img->height, 0);
|
||||
D3D11_SUBRESOURCE_DATA initial_data {
|
||||
dummy_data.get(),
|
||||
(UINT) img->row_pitch,
|
||||
0
|
||||
};
|
||||
status = device->CreateTexture2D(&t, &initial_data, &img->capture_texture);
|
||||
}
|
||||
else {
|
||||
status = device->CreateTexture2D(&t, nullptr, &img->capture_texture);
|
||||
}
|
||||
auto status = device->CreateTexture2D(&t, nullptr, &img->capture_texture);
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(error) << "Failed to create img buf texture [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user